人物判定

pythonopencvを使って特定の人物がうつっているかを判定してみました。
今回は下のサイトのプログラムを改造して作りました。
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枚で作りました。
f:id:katatsumuri527:20200511094515p:plain
プログラムを動かすと意外ときちんと認識してくれます。
別の猫では認識しません。
背景を変えても認識します。
f:id:katatsumuri527:20200511094730j:plain
もちろんすごく似た猫は認識できない可能性はあります