OpenCVで画像・映像加工処理 画像や映像を好き勝手加工してみる パート2 ヒストグラムの作成とモザイク加工
画像や映像を好き勝手加工してみる パート2 ~ヒストグラムの作成とモザイク加工~
OpenCVで画像・映像加工処理
こんにちは。目指せ!脱コボラー!のsakaです。
前回に引き続き、Python×OpenCVで、画像や映像を加工してみた話です。
パート2では、ヒストグラムの作成とモザイク加工についてです。
具体的には、以下の4つを紹介します。
・ヒストグラム
・座標指定のモザイク
・顔モザイク,目モザイク
・Webカメラで目モザイク
前準備
・必要なモジュールを用意
matplotlib.pyplot
自動的に図形や軸を作成するインターフェース
・以下のコマンドを実行
pip install matplotlib
・フォルダ構造
/rgb/
/facemosaic.py ## new
/gray.py
/hist.py ## new
/mosaic.py ## new
/replace.py
/rgb.py
/webmosaic.py ## new
/img/
/fruit.jpg
/nicemans.png ## new
この画像を加工していきます。
・ヒストグラム
(fruit.jpg)

・それ以外
(nicemans.png)

プログラム
・ヒストグラム
matplotlib.pyplotを使用
python:hist.py
import cv2
import numpy as np
import os
import matplotlib.pyplot as plt
PATH = './img'
FILES = os.listdir(PATH)
COLOR = ('b', 'g', 'r')
# get file name
def get_file_name():
print('*** All Pictures ***')
print(*FILES, sep='\n')
print('*** End ***')
while True:
file_name = input('Which use file name ?: ')
if file_name in FILES:
return file_name
else:
print('not exist: ' + file_name)
if __name__ == '__main__':
file_name = get_file_name()
file_prefixes = file_name.rsplit('.', 1)
simple_file_name = file_prefixes[0]
# 元の画像を読み込む
file_img = cv2.imread(PATH + '/'+ file_name, cv2.IMREAD_COLOR)
# ウィンドウを作成
cv2.namedWindow(simple_file_name)
# ウィンドウに表示
cv2.imshow(simple_file_name, file_img)
for i, col in enumerate(COLOR):
histr = cv2.calcHist([file_img], [i], None, [256], [0, 256])
plt.plot(histr, color = col)
plt.xlim([0,256])
plt.show()
# 終了処理
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.calcHistでヒストグラムを計算することができます。
赤系が多いため、ヒストグラムの赤線も右寄りになっています。
(hist.png)

・座標指定のモザイク
モザイクは指定した位置を縮小し、拡大で戻したものを使用している。
import cv2
import numpy as np
import os
PATH = './img'
FILES = os.listdir(PATH)
OLD_WINDOW_NAME = 'old'
NEW_WINDOW_NAME = 'new'
# モザイクの粗さ
ratio = 0.1
# get file name
def get_file_name():
print('*** All Pictures ***')
print(*FILES, sep='\n')
print('*** End ***')
while True:
file_name = input('Which use file name ?: ')
if file_name in FILES:
return file_name
else:
print('not exist: ' + file_name)
def mosaic(src):
small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)
def mosaic_area(src, x, y, width, height):
dst = src.copy()
dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width])
return dst
if __name__ == '__main__':
old_file_name = get_file_name()
file_prefixes = old_file_name.rsplit('.', 1)
new_file_name = file_prefixes[0] + '_after.' + file_prefixes[1]
# 元の画像を読み込む
old_img = cv2.imread(PATH + '/'+ old_file_name)
# モザイク化
new_img = mosaic_area(old_img, 100, 50, 100, 150)
# ウィンドウを作成
cv2.namedWindow(OLD_WINDOW_NAME)
cv2.namedWindow(NEW_WINDOW_NAME)
# ウィンドウに表示
cv2.imshow(OLD_WINDOW_NAME, old_img)
cv2.imshow(NEW_WINDOW_NAME, new_img)
# ファイルに保存
cv2.imwrite(r'img/{}'.format(new_file_name), new_img)
# 終了処理
cv2.waitKey(0)
cv2.destroyAllWindows()
ratioが小さければ小さいほど粗いモザイクが作成される。
(nicemans_mosaic.png)

・顔モザイク,目モザイク
顔の学習データ “[haarcascade_frontalface_alt.xml](https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_alt.xml)” を使用する。
python:facemosaic.py
import cv2
import numpy as np
import os
PATH = './img'
FILES = os.listdir(PATH)
FACE_CASCADE_PATH = "haarcascade_frontalface_alt.xml"
FACE_CASCADE = cv2.CascadeClassifier(FACE_CASCADE_PATH)
ratio = 0.05
# get file name
def get_file_name():
print('*** All Pictures ***')
print(*FILES, sep='\n')
print('*** End ***')
while True:
file_name = input('Which use file name ?: ')
if file_name in FILES:
return file_name
else:
print('not exist: ' + file_name)
def mosaic(src):
small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)
def mosaic_area(src, x, y, width, height):
dst = src.copy()
dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width])
return dst
if __name__ == '__main__':
old_file_name = get_file_name()
file_prefixes = old_file_name.rsplit('.', 1)
new_file_name = file_prefixes[0] + '_after.' + file_prefixes[1]
# 元の画像を読み込む
old_img = cv2.imread(PATH + '/'+ old_file_name)
new_img = np.copy(old_img)
# グレイスケール,学習データ精査
gray_frame = cv2.cvtColor(new_img, cv2.COLOR_RGB2GRAY)
front_face_list = FACE_CASCADE.detectMultiScale(gray_frame, minSize = (50, 50), minNeighbors=5)
# 認識された顔の数
face_count = str(len(front_face_list))
cv2.putText(new_img, face_count.zfill(3), (0,30), cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 0), 3, cv2.LINE_AA)
# モザイク化
for (x, y, w, h) in front_face_list:
new_img = mosaic_area(new_img, x, y, w, h)
cv2.rectangle(new_img, (x, y), (x + w, y + h), (0, 0, 255), thickness=3)
cv2.imshow('OldRawFrame', old_img)
cv2.imshow('NewRawFrame', new_img)
cv2.imwrite(r'img/{}'.format(new_file_name), new_img)
# 終了処理
cv2.waitKey(0)
cv2.destroyAllWindows()
(nicemans_faces.png)

グレイスケールしたデータを学習データで精査し、顔を認識してくれます。
このように niceman が複数人いてもきちんと数えられている。
さらに修正して、目線にモザイクを付けるようにしてみた。
python:facemosaic.py
FACE_CASCADE_PATH = "haarcascade_frontalface_alt.xml" FACE_CASCADE = cv2.CascadeClassifier(FACE_CASCADE_PATH) # 追加 EYE_CASCADE_PATH = "haarcascade_eye.xml" EYE_CASCADE = cv2.CascadeClassifier(EYE_CASCADE_PATH) # モザイク化 for (x, y, w, h) in front_face_list: # new_frame = mosaic_area(new_frame, x, y, w, h) # 削除 cv2.rectangle(new_img, (x, y), (x + w, y + h), (0, 0, 255), thickness=3) # 追加 eye_list = EYE_CASCADE.detectMultiScale(gray_frame, minNeighbors=40) for (ex, ey, ew, eh) in eye_list: if x < ex and y < ey and x + w > ex + ew and y + h > ey + eh: new_frame = mosaic_area(new_frame, x, ey, w, eh)
(nicemans_eyes.png)

目の学習データ [haarcascade_eye.xml](https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_eye.xml) を使用した
EYE_CASCADE.detectMultiScale(gray_frame, minNeighbors=40)
minNeighbors=40にすることにより、誤検知を少なくする。
また、赤枠(顔検知)外で目と検知されたものも対象外となるようにした。
・Webカメラで目モザイク
python:webmosaic.py
import cv2
cap = cv2.VideoCapture(0)
face_cascade_path = "haarcascade_frontalface_alt.xml"
eye_cascade_path = "haarcascade_eye.xml"
face_cascade = cv2.CascadeClassifier(face_cascade_path)
eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
if __name__ == '__main__':
while True:
ret, old_frame = cap.read()
new_frame = old_frame.copy()
gray_frame = cv2.cvtColor(new_frame, cv2.COLOR_RGB2GRAY)
front_face_list = face_cascade.detectMultiScale(gray_frame, minSize = (50, 50), minNeighbors=3)
face_count = str(len(front_face_list))
cv2.putText(new_frame, face_count.zfill(3), (500,50), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 5, cv2.LINE_AA)
for (x, y, w, h) in front_face_list:
eye_list = eye_cascade.detectMultiScale(gray_frame, minNeighbors=20)
for (ex, ey, ew, eh) in eye_list:
if x < ex and y < ey and x + w > ex + ew and y + h > ey + eh:
cv2.rectangle(new_frame, (x+10, ey), (x + w-10, ey + eh), (0, 0, 0), thickness=-1)
cv2.rectangle(new_frame, (x, y), (x + w, y + h), (0, 0, 255), thickness=3)
cv2.imshow('OldRawFrame', old_frame)
cv2.imshow('NewRawFrame', new_frame)
k = cv2.waitKey(1)
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
基本的にfacemosaic.pyと同じプログラムです。
cv2.VideoCaptureでデバイス番号0のカメラを起動して、処理を行なっている。
眼鏡や横顔などはまだ反応できないことがあるが、目モザイクを付けることができた!
まとめ
Webカメラを使用したモザイク加工をすることができた。
ラズパイなどに活用して、監視カメラや顔認証ができるのではないかと思いました。
また、動物やモノを学習データとしてinputさせてあげれば、それらを検知することができるのではないかと思いました。
良いデータが見つかればまた動かしてみようと思います。
以上です!
Tweet