人の顔にマスクを着けるPythonプログラムを紹介します
人の顔にマスクを合成して、マスクを着けているように見えるPythonプログラムの紹介とその説明。そして、顔とマスクを合成した画像を投稿します。
人の顔が写っている画像は「ぱくたそ」さんの画像を使いました。
黒色背景のマスクは私がスマホで撮った写真になります。
この投稿以外に画像合成プログラムを紹介している投稿がこちら↓になります。
「画像合成を交えて色を数値で確認する方法 Python」
「Pythonを使った画像合成をColaboratoryで実行」
「画像合成で使う緑色背景の色を変更 Python」
「画像合成で使う画像の色を数値で確認する方法」
目次
・画像合成で使った顔が写っている画像
・画像合成で使ったマスクの画像
・顔にマスクを合成するPythonプログラム
・Pythonプログラムを使って顔にマスクを合成した画像
・1月28日 修正
画像合成で使った顔が写っている画像



画像合成で使ったマスクの画像

このマスク画像について
顔が大きい、小さいでマスク画像のサイズを変えて合成していたら、汎用性がないと思ったので、顔が大きい、小さい関係なしにちょうどいいくらいのサイズにしています。
顔にマスクを合成するPythonプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
import cv2 import numpy as np import matplotlib.pyplot as plt def mask_gousei(img,mask):# #読み込んだ人画像の表示 img_show=cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img_show) plt.show() #読み込んだマスク画像の表示 mask_show=cv2.cvtColor(mask, cv2.COLOR_BGR2RGB) plt.imshow(mask_show) plt.show() img_gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#グレイ画像 images = face_cascade.detectMultiScale(img_gray)#顔の検出 for x,y,w,h in images:#顔検出した座標の数繰り返す face=img[y:y+h,x:x+w]#顔切り取る face_gray=img_gray[y:y+h,x:x+w]#顔のグレイ画像 eye = eye_cascade.detectMultiScale(face_gray)#グレーにした顔から目を検出 if len(eye) != 0:#目を検出できたら変数eyeに目の座標が入ります #検出した顔の表示 face_show=cv2.cvtColor(face, cv2.COLOR_BGR2RGB) plt.imshow(face_show) plt.show() half=img[y+h//2:y+h,x:x+w]#顔下半分の画像を変数halfに入れる d1=y+h//2#人画像に合成したマスクを埋め込むときに使う d2=y+h d3=x d4=x+w #顔の下半分表示 half_show=cv2.cvtColor(half, cv2.COLOR_BGR2RGB) plt.imshow(half_show) plt.show() height, width = half.shape[:2]#顔の下半分の高さ、幅を取り出す mask=cv2.resize(mask,(width,height))#顔の下半分とマスクの大きさを合わせる for x in range(height):#マスクの背景の色を取り除いて、顔の下半分にマスクを合成 for y in range(width): b, g, r = mask[x, y]#色を取り出す if (b >= 0 and b <= 160) and (g >= 0 and g <= 160) and (r >= 0 and r <= 160):#黒色背景を除く continue half[x, y]=mask[x, y]#合成 #マスクを合成した画像を表示 half_show=cv2.cvtColor(half, cv2.COLOR_BGR2RGB) plt.imshow(half_show) plt.show() img[d1:d2,d3:d4]=half#人画像にマスクを合成した画像を埋め込む return img face_cascade=cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")#顔を検出するカスケードファイル eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")#目を検出するカスケードファイル mask_img=cv2.imread("DSC_1210 (5).jpg")#マスク画像 human_img=cv2.imread("face_03.jpg")#人画像 face_mask=mask_gousei(human_img,mask_img)#マスクを合成する自作関数に、人の画像とマスクの画像を渡す #元画像にマスクを合成した画像を表示 face_mask_show=cv2.cvtColor(face_mask, cv2.COLOR_BGR2RGB) plt.imshow(face_mask_show) plt.show() |
プログラムの説明をします。
24行目のif len(eye) != 0は顔検出してから、目の検出ができたかどうかの判定をしています。
検出した顔が複数あった場合、そこから、目を検出できた箇所を本物の顔とすることで、顔以外のところを顔と検出されたときの対応をしています。
31行目はimg[y+h//2:y+h,x:x+w]で読み込んだ人画像から検出した顔の下半分を切り取って変数halfに代入しています。20行目のimg[y:y+h,x:x+w]は検出した顔をそのまま切り取っています。
32~35行目の変数d1~d4は57行目の顔下半分にマスクを合成した画像を埋め込む際に使う変数です。
43行目はcv2.resizeでマスクの大きさを顔下半分の大きさに合わせています。
48行目の0~160の値はペイントで黒色背景の色を数値で確認したときの値になります。
ペイントで画像の色を数値で確認する方法はこちら↓で紹介しています。
「画像合成で使う画像の色を数値で確認する方法」
「画像合成を交えて色を数値で確認する方法 Python」
50行目は黒色背景以外のマスクの部分だけを顔下半分に合成しています。
以下がmatplotlibのplt.imshow()で表示している様子になります。
① 読み込んだ人画像を表示

② 読み込んだマスク画像を表示

③ 顔検出した部分を切り取って表示

④ 顔下半を表示

⑤ 顔下半分にマスクを合成して表示

⑥ ④の画像データを①の画像データに埋め込んで表示

Pythonプログラムを使って顔にマスクを合成した画像



動画に写る顔にマスクを合成している様子はこちら↓になります。
「Pythonプログラムで動画に写る人の顔にマスクを着ける方法」
1月28日 修正 顔にマスクを合成するPythonプログラム
上のプログラムは顔と目を検出できなかった場合、エラーがでてしまうので、
顔と目を検出できなかった場合を考慮したプログラムを下に載せておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
import cv2 import numpy as np import matplotlib.pyplot as plt def mask_gousei(img,mask):# half=[] #読み込んだ人画像の表示 img_show=cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img_show) plt.show() #読み込んだマスク画像の表示 mask_show=cv2.cvtColor(mask, cv2.COLOR_BGR2RGB) plt.imshow(mask_show) plt.show() img_gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#グレイ画像 images = face_cascade.detectMultiScale(img_gray)#顔の検出 if len(images) != 0:#顔を検出できた場合 for x,y,w,h in images:#顔検出した座標の数繰り返す face=img[y:y+h,x:x+w]#顔切り取る face_gray=img_gray[y:y+h,x:x+w]#顔のグレイ画像 eye = eye_cascade.detectMultiScale(face_gray)#グレーにした顔から目を検出 if len(eye) != 0:#目を検出できた場合 変数eyeに目の座標が入ります #検出した顔の表示 face_show=cv2.cvtColor(face, cv2.COLOR_BGR2RGB) plt.imshow(face_show) plt.show() half=img[y+h//2:y+h,x:x+w]#顔下半分の画像を変数halfに入れる d1=y+h//2#人画像に合成したマスクを埋め込むときに使う d2=y+h d3=x d4=x+w #顔の下半分表示 half_show=cv2.cvtColor(half, cv2.COLOR_BGR2RGB) plt.imshow(half_show) plt.show() else:#for文の繰り返しがすべて終わるまで、continue continue if len(half) != 0:#顔の検出と目の検出、両方ができた場合 height, width = half.shape[:2]#顔の下半分の高さ、幅を取り出す mask=cv2.resize(mask,(width,height))#顔の下半分とマスクの大きさを合わせる for x in range(height):#マスクの背景の色を取り除いて、顔の下半分にマスクを合成 for y in range(width): b, g, r = mask[x, y]#色を取り出す if (b >= 0 and b <= 160) and (g >= 0 and g <= 160) and (r >= 0 and r <= 160):#黒色背景を除く continue half[x, y]=mask[x, y]#合成 #マスクを合成した画像を表示 half_show=cv2.cvtColor(half, cv2.COLOR_BGR2RGB) plt.imshow(half_show) plt.show() img[d1:d2,d3:d4]=half#人画像にマスクを合成した画像を埋め込む return img else:#顔は検出できたが、目を検出できなかった場合 読み込んだ画像をそのまま返す return img else:#顔を検出できなかった場合 読み込んだ画像をそのまま返す return img face_cascade=cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")#顔を検出するカスケードファイル eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")#目を検出するカスケードファイル mask_img=cv2.imread("DSC_1210 (5).jpg")#マスク画像 human_img=cv2.imread("face_03.jpg")#人画像 face_mask=mask_gousei(human_img,mask_img)#マスクを合成する自作関数に、人の画像とマスクの画像を渡す #元画像にマスクを合成した画像を表示 face_mask_show=cv2.cvtColor(face_mask, cv2.COLOR_BGR2RGB) plt.imshow(face_mask_show) plt.show() |
顔と目を検出できなかった場合は引数に渡した画像をそのままreturnで呼び出し元に返すようにしているので、マスクを合成していない画像が表示されます。