動画の解説を参照
今回は実写 (風) の画像を使って顔検出を行い、顔の部分にぼかしやモザイクを加えます。
元画像は複数の人の顔が写った実写 (風) の画像にしてください。
※ 顔認識にはある程度のサイズが必要です。以下の顔認識がうまくいかない場合は元画像を変更してください。
参考 :
haconana (AI生成された画像の無料DLサイト)
元画像を決めたら、以降の変換の元になる画像変数「img」を作っておきます。
(この時点では読み込むだけで、画像は出力しません)
import cv2
import numpy as np
from google.colab import files
file = files.upload()
filename = next(iter(file))
img = cv2.imread(filename)
動画の解説を参照
OpenCVで顔検出を行うには、まず「顔検出器」を用意する必要があります。
以下のようにすれば顔検出器 face_cascade が使えるようになります。
(これはOpenCVのデフォルトの顔検出器を使うための記述です。自分でXML形式のファイルを記述して顔検出器を作ることもできます)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
こうしてから以下のようなコードを実行すると、検出された顔の位置・大きさの情報のリストが faces に入ります。
内部的には、元のサイズで検出を行ったあと 1/scaleFactor の倍率でスケーリングしてふたたび検出、さらに 1/scaleFactor のような処理を行います。
このように繰り返したときに minNeighbors 回以上顔と認識された部分が最終的に顔と判定されます。
なお、minSizeより小さい部分は判定対象から除外します。
faces = face_cascade.detectMultiScale(img, scaleFactor=?, minNeighbors=?, minSize=(?, ?))
これらのパラメータの組合せによって、顔が適切に取り出されるかどうかが変わります。
そこで、入れ子のfor文でこの3つのパラメータを適当な範囲で変えて、顔が何個検出されたかをリスト表示します。
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
scale_foctors = [1.05, 1.1, 1.2]
min_neghbors = [3, 4, 5]
min_sizes = [(30, 30), (40, 40), (50, 50)]
for scale_factor in scale_foctors:
for min_neighbor in min_neghbors:
for min_size in min_sizes:
faces = face_cascade.detectMultiScale(img, scaleFactor=scale_factor, minNeighbors=min_neighbor, minSize=min_size)
print (f"Scale Factor: {scale_factor}, Min Neighbors: {min_neighbor}, Min Size: {min_size}, faces: {len(faces)}")
上の説明で使ったサンプルの元画像ではこのようになりました。
人間の目では、はっきり写っている顔は3人分なので、赤枠のパラメータの組合せが適切だろうということがわかります。
動画の解説を参照
前項の方法で見つけた適切なパラメータを引数として detectMultiScale に渡して得られる faces は、顔の左上の位置の横と縦の座標 x, y、顔の横・縦の幅 w, h の情報のリストです。
そこで、すべての顔についての繰り返しを行い、その位置に長方形を描きます。
rectangle関数の5番目の引数は線の太さです。
img2 = img.copy()
faces = face_cascade.detectMultiScale(img, scaleFactor=?, minNeighbors=?, minSize=(?, ?))
for (x, y, w, h) in faces:
cv2.rectangle(img2, (x, y), (x+w, y+h), (255, 0, 0), ?)
cv2.imwrite('ex2.jpg', img2)
顔検出を行い、顔の部分に青枠を入れた画像 ex2.jpg を出力してください。
※ detectMultiScaleの係数には、課題1の結果を踏まえて適切な値を入れてください。
※ rectangle関数の第5パラメータを調整し、青枠の太さを適切なものにしてください。
(例 : 左の人物は顔に指がかかっていたためか、課題1で適切と思われたパラメータでは検出できていません。3人目は後ろのぼやけた人物でした)
動画の解説を参照
facesの各要素はそれぞれの顔の位置・大きさの情報を持っているので、元画像からその部分だけを切り出して「顔だけの画像」をつくることができます。
face = img3[y:y+h, x:x+w]
これに
第5回でやった平滑化の処理を行うと、その顔をぼやけさせることができます。
face = cv2.GaussianBlur(face, (99, 99), 30)
さらに、このぼやけた画像を元画像の顔がある位置に上描きすれば、結果として顔の部分だけがぼやけた画像になります。
img3[y:y+h, x:x+w] = face
img3 = img.copy()
for (x, y, w, h) in faces:
face = img3[y:y+h, x:x+w]
face = cv2.GaussianBlur(face, (99, 99), 30)
img3[y:y+h, x:x+w] = face
cv2.imwrite('ex3.jpg', img3)
顔にぼかしを入れた画像 ex3.jpg を出力してください。
(例)
動画の解説を参照
顔にモザイクをかけるには、まず前項と同様にして取り出した「顔だけ画像」を、元の 1/? のサイズに縮小します。
face = cv2.resize(face, (w//?, h//?))
これをまた元と同じサイズになるように拡大すると、結果としてモザイクのかかった顔画像ができます。
face = cv2.resize(face, (w, h), interpolation=cv2.INTER_NEAREST)
あとは前項と同様にこの画像を元の位置に描き戻してやれば、顔だけにモザイクがかかった画像ができます。
img4 = img.copy()
for (x, y, w, h) in faces:
face = img4[y:y+h, x:x+w]
face = cv2.resize(face, (w//?, h//?))
face = cv2.resize(face, (w, h), interpolation=cv2.INTER_NEAREST)
img4[y:y+h, x:x+w] = face
cv2.imwrite('ex4.jpg', img4)
顔にモザイクを入れた画像 ex4.jpg を出力してください。
動画の解説を参照
今回作成したノートブックを「imgprc2024@gmail.com」と共有してください。
※ 第2回で共有した、画像共有用の「画像処理」フォルダの中に「第13回」フォルダを作り、その中に今回の元画像と出力画像を入れてください。
※ 課題の再提出の際は、ノートブックの再度の共有はせずにチャットで連絡してください。