MENU

python opencvの顔検出は完璧ではない

傾いた顔の画像は検出できないことを確認していく。

f:id:hanamichi_sukusuku:20201222193514p:plain

実行結果

f:id:hanamichi_sukusuku:20201222193533p:plain

import matplotlib.pyplot as plt
import cv2
from scipy import ndimage

まずモジュール読み込み。

scipyはpythonの科学技術計算ライブラリでnumpyがないと使えない。

簡単に言えば高度な計算ができるライブラリ。

 

次に検出器と画像の読み込み

# 検出器と画像の読み込み
cascade_file = "haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_file)
img = cv2.imread("girl.jpg")

カスケードファイルをcv2.CascadeClassifierに引数として渡して検出器を作成。

 

# 顔検出を実行し、印をつける
def face_detect(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face_list = cascade.detectMultiScale(img_gray, minSize=(300,300))
# 認識した部分に印をつける
for (x,y,w,h) in face_list:
print("顔の座標=", x, y, w, h)
red = (0, 0, 255)
cv2.rectangle(img, (x, y), (x+w, y+h), red, thickness=30)

この関数に関しては、引数で画像データを渡してグレイスケールに変換。

cascade.detectMultiScaleメソッドで検出を行っている。

その後、検出されたデータの顔座標の表示とcv2.rectangleで元の画像に長方形で検出したデータを描画している。

cv2.rectangleは長方形描画するときに使う。

cv2.rectangle(描画する画像,(左上からのx座標, y座標),(x+w(幅), y+h(高さ)),色,線の太さとかオプション)

thicknessは線の太さを変えるオプション。

 

# 角度毎に検証する
for i in range(0, 9):
ang = i * 10
print("---" + str(ang) + "---")
img_r = ndimage.rotate(img, ang)
face_detect(img_r)
plt.subplot(3, 3, i + 1)
plt.axis("off")
plt.title("angle=" + str(ang))
plt.imshow(cv2.cvtColor(img_r, cv2.COLOR_BGR2RGB))
 
plt.show()

最後に画像を傾かせ、先ほどのface_detect()関数で傾かせた画像を処理したものを表示している。

細かくみていくとrange(0, 9)で9回処理を繰り返している。

range(x, y) x(start) <= i < y(stop)の連番が生成される。今回だと0~8。

scipy.ndimageモジュールのrotate( )関数で画像を回転させている。

rotate(傾かせたい画像, 角度)このように指定できる。

次にface_detect()関数を呼び出して処理。

plt.subplot()で複数のプロットを一枚の画像の中に表示することができる。

plt.subplot(行数,列数,subplotの中で左上から数えて何番目か)で指定できる。

plt.axis("off")を指定することでグラフの軸や枠をなくすことができる。

下記はplt.axis("off")を指定していない場合。

f:id:hanamichi_sukusuku:20201222195603p:plain

 

 

 

 

 まとめ

正面かつ顔が傾いていないと検出されないようではまだまだ実用的な知識は身についていないのかなと感じるのでまずは画像解析をマスターしていこうと思います。