前回は認識した顔を四角で囲うところまでやってみました。今回は、顔にモザイクを書けてみたいと思います。
##モザイクのアルゴリズム
モザイクは画像のサイズを一度小さくし、元の画像サイズに単純に拡大することで簡単に実装できます。縮小時に画素の平均値が取られたりしているわけですので、実際のアルゴリズム自体はもう少し複雑ですが、処理自体は単純に縮小→拡大してあげればOKです。
以下のようなコードになります。
for rect in facerect:
#矩形描画
cv2.rectangle(img, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), (255,255,255),3)
#顔部分の画像の切り出し
cut_img = img[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
#20分の1のサイズに縮小
cut_img = cv2.resize(cut_img,(rect[2]//20, rect[3]//20))
#元のサイズに戻す。cv2.INTER_NEARESTを使わないと滑らかになる。
cut_img = cv2.resize(cut_img,(rect[2], rect[3]),cv2.INTER_NEAREST)
#切り出した画像で元の画像を置き換え
img[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]=cut_img
python2.7系と3系だと少しコードの書き方が異なります。3系ですと、rect[2]/20ではなくて、//を使う必要があります。また、cv2.INTER_NEARESTもpython2だとcv2.cv.cv_INTER_NNになる点に注意です。
また、imgは[y:y+h,x:x+w]と、顔の配列の(x,y,w,h)と順番が異なることにも注意しましょう。
最終的には以下のようなコードになりました。
# -*- coding: utf-8 -*-
import cv2
import time
cascade_path="D:\python\OpenCV\opencv\sources\data\haarcascades\haarcascade_frontalface_default.xml"
window = "Push ESC key to stop this program"
def detect_face(img):
cascade = cv2.CascadeClassifier(cascade_path)
facerect = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1, minSize=(100, 100))
#顔の数だけ処理
if len(facerect) > 0:
for rect in facerect:
#矩形描画
cv2.rectangle(img, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), (255,255,255),3)
cut_img = img[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
cut_img = cv2.resize(cut_img,(rect[2]//20, rect[3]//20))
cut_img = cv2.resize(cut_img,(rect[2], rect[3]),cv2.INTER_NEAREST)
img[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]=cut_img
cv2.imshow(window, img)
print(facerect)
if(__name__ == '__main__'):
# デフォルトカメラは0
capture = cv2.VideoCapture(1)
# キャプチャ処理
while(True):
key = cv2.waitKey(5)
if(key == 27):
print("exit.")
break
# 画像キャプチャ
ret, img = capture.read()
# 取り込み開始になっていなかったら上の処理に戻る
if(ret == False):
print("Capture Failed. ")
break
#顔検出
detect_face(img)
time.sleep(0.050)
capture.release()
cv2.destroyAllWindows()
実行してみましたが、無事に顔にモザイクがかかりました。
##まとめ
今回は認識した顔にモザイクをかけてみました。一見複雑そうな画像処理もシンプルなアルゴリズムで実現できるケースがあるのですね。これまではサンプルに付属した分類器を利用していましたが、次回は、この分類器を自分で定義してみたいと思います。
注:動かしてみると、たまに止まるのでこのプログラムには何処かに問題があると思われます。