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