人物判定
pythonとopencvを使って特定の人物がうつっているかを判定してみました。
今回は下のサイトのプログラムを改造して作りました。
symfoware.blog.fc2.com
リアルタイムで処理するプログラムです。
処理が重いのでカクカクしますがちゃんと認識します。
import numpy import cv2 import glob img_list = [] for i in glob.glob("./img/face/*.jpg"): #パスは顔写真の入っているファイルのパスにする test_file = i test_image = cv2.imread(test_file) img_list.append(test_image) def calc(matcher_name, face_image): detector = cv2.ORB_create() keypoints1 = detector.detect(face_image) descripter = cv2.ORB_create() k1,d1 = descripter.compute(face_image, keypoints1) matcher = cv2.DescriptorMatcher_create(matcher_name) min_dist = 100000 for i in range(len(img_list)): keypoints2 = detector.detect(img_list[i]) k2,d2 = descripter.compute(img_list[i], keypoints2) try: matches = matcher.match(d1, d2) except: continue dist = [m.distance for m in matches] if len(dist) == 0: continue min_dist = min(min(dist), min_dist) return min_dist cascade_path = 'cascade/haarcascade_frontalface_alt.xml' #opencvのカスケード分類器のパス cam = cv2.VideoCapture(0) while True: _, image = cam.read() image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cascade = cv2.CascadeClassifier(cascade_path) facerect = cascade.detectMultiScale( image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1)) if len(facerect) <= 0: pass else: rect = facerect[0] for r in facerect: if rect[2] < r[2]: rect = r x = rect[0] y = rect[1] w = rect[2] h = rect[3] face_image = image_gray[y:y+h, x:x+w] resutl = calc('BruteForce-Hamming', face_image) cv2.imshow("detected_", face_image) key = cv2.waitKey(1) & 0xFF if key == ord('q'): break if resutl < 10: #ここの数字を変えることで閾値が変わる。 print('認識しました') cam.release() cv2.destroyAllWindows()
このプログラムを動かすには初めに認識したい特定の人物のグレースケールの顔写真が必要なので写真を20枚ほど撮って
次のプログラムでグレースケールにし、顔の部分を切り取ります。
# -*- coding:utf-8 -*- import numpy import cv2 import glob cascade_path = 'cascade/haarcascade_frontalface_alt.xml' list_ = glob.glob("img/face/*.jpg") print(list_) for i in list_: image = cv2.imread(i) image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cascade = cv2.CascadeClassifier(cascade_path) facerect = cascade.detectMultiScale( image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1)) print(i, len(facerect)) if len(facerect) <= 0: continue rect = facerect[0] for r in facerect: if rect[2] < r[2]: rect = r x = rect[0] y = rect[1] w = rect[2] h = rect[3] # img[y: y + h, x: x + w] cv2.imwrite(i, image_gray[y:y+h, x:x+w])
写真をグレースケールに変換し、顔部分だけを切り取ってファイルを置き換えています。
光のあたり加減や場所によって変わるので閾値を変えてください。
似たような顔のひとは識別できない可能性があります。
上のプログラムを応用して特定の猫を検出するプログラムを作りました。
作ったプログラムはこちらです。
import numpy import cv2 import glob img_list = [] for i in glob.glob("./img/neko/*.jpg"): test_file = i test_image = cv2.imread(test_file) img_list.append(test_image) def calc(matcher_name, face_image): detector = cv2.ORB_create() keypoints1 = detector.detect(face_image) descripter = cv2.ORB_create() k1,d1 = descripter.compute(face_image, keypoints1) matcher = cv2.DescriptorMatcher_create(matcher_name) min_dist = 100000 for i in range(len(img_list)): keypoints2 = detector.detect(img_list[i]) k2,d2 = descripter.compute(img_list[i], keypoints2) try: matches = matcher.match(d1, d2) except: continue dist = [m.distance for m in matches] if len(dist) == 0: continue min_dist = min(min(dist), min_dist) return min_dist cascade_path = 'cascade/neko.xml' image = cv2.imread("img/neko.jpg") #認識させたい画像ファイルのパス image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cascade = cv2.CascadeClassifier(cascade_path) facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1)) if len(facerect) <= 0: pass else: rect = facerect[0] for r in facerect: if rect[2] < r[2]: rect = r x = rect[0] y = rect[1] w = rect[2] h = rect[3] # img[y: y + h, x: x + w] face_image = image_gray[y:y+h, x:x+w] resutl = calc('BruteForce-Hamming', face_image) print(resutl) if resutl < 5: print('cat') cv2.imshow("cat", face_image) cv2.waitKey(1)
猫の顔を切り取るには上のプログラムのカスケード分類器の部分を置き換えてください。
使ったカスケード分類器は下のサイトで配布されていたものを使いました。
rest-term.com
同じ猫の画像が配布されているところがなかったので下のサイトの動画から写真を取り出して作りました。
movie-labo.info
猫の写真は10枚で作りました。
プログラムを動かすと意外ときちんと認識してくれます。
別の猫では認識しません。
背景を変えても認識します。
もちろんすごく似た猫は認識できない可能性はあります