福岡人データサイエンティストの部屋

データサイエンスを極めるため、日々の学習を綴っています。

【OpenCV】画像の顔検出&モザイク処理【Python】



こんにちは!こーたろーです。


OpenCVレーニング第3回目は、モザイク処理です。


第2回目で顔を検出しましたので、その検出した顔に対してモザイク処理をしてみます。


今回もサンプル画像はフリー素材から持ってきて、やっていきます。


それでは早速ハンズオンやっていきましょう!


ライブラリのインポート



これまで通り、画像を制御するためのOpenCVと画像を表示するためのmatplotlib、画像をWebから取得するためのurllibをインポートします。

import cv2
import matplotlib.pyplot as plt
import urllib.request as req


画像データの取得



フリー画像を検索して、画像のURLをコピーしてurlとして変数に格納しておきます。


Webリクエストした画像を変数に入れて保存(img)します。
その後、RGBの3チャネルの画像を、顔検出のためにグレースケールに変換して別変数(img_gray)へ格納します。

url = "https://pbs.twimg.com/media/DfQN7W8V4AECxVc?format=jpg&name=large"
req.urlretrieve(url, "face_download.jpg")

img = cv2.imread("face_download.jpg")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


カスケードファイルの定義と検出器の作成・顔の検出



顔検出のためのカスケードファイルを準備します。


"haarcascade_frontalface_alt.xml"をGitHubからダウンロードし、ルートフォルダ内に配置しておきます。


cascade.detectMultiScale関数を使って、顔を検出します。複数検出した場合は、tupleの配列としてface_listに格納されます。


今回は2つの顔が検出されました。

cascade_file = "haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_file)
face_list = cascade.detectMultiScale(img_gray, minSize = (150, 150))

for x, y, w, h  in face_list:
    print("顔の座標 =", x, y, w, h)
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), thickness = 5)

plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()





モザイク処理の定義



モザイク処理をする関数を定義します。


モザイク処理の関数へは、face_listのtupleを渡します。


それから、モザイクの粒度をsizeとして定義し引数として渡します。


結果、「元の画像」「検出したface_list」「モザイクサイズ」を引数としています。

def mosaic(img, coordinate, size):
    (x, y, h, w) = coordinate
    x2 = x + w
    y2 = y + h
    img_coordinate = img[y:y2, x:x2]
    img_small = cv2.resize(img_coordinate, (size, size))
    img_mosaic = cv2.resize(img_small, (w, h), interpolation = cv2.INTER_AREA)
    
    img2 = img.copy()
    img2[y:y2, x:x2] = img_mosaic
    return img2



モザイク処理では、検出した顔画像の部分を切り取って、リサイズにて一度小さくしたうえで、再度サイズを復元します。


この際に、「interpolation」として、画素の補間について定義しています。


今回は「INTER_AREA」を選択しています。これは、ピクセル領域の関係を利用したリサンプリング方法になります。
他にも、

  • 「INTER_NEAREST : 最近傍補間
  • 「INTER_LINEAR : バイリニア補間」
  • 「INTER_CUBIC : バイキュービック補間」
  • 「INTER_LANCZOS4 : Lanczos 補間」などがあります。



最後に、モザイクをかけた部分について、原画像の顔部分のデータと差し替えてモザイク処理完了です。

モザイク処理後の結果の表示



モザイク処理を実際に実行し、その結果を表示させます。

for (x, y, w, h) in face_list:
    img = mosaic(img, (x, y, w, h), 10)

plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()






無事に顔を検出した領域にモザイクを掛けることができました。


調べた結果、この方法での顔検出は、横向きや顔の軸が回転している場合には検出が難しいようです。


それを鑑みて、次回は別の手法での顔検出を行ってみたいと思います。


ではでは。


OpenCVではじめよう ディープラーニングによる画像認識