2016-05-15 15:15

人脸识别与身份认证

在测试色度图像识别的过程中顺便测试的一段使用OpenCV自带特征库对Camera进行人脸识别的Demo,识别率不错。但身份认证的算法一般,这里也就没有提供 pHash 的代码。

import os, glob
import sys
import cv2
import numpy as np
from PIL import Image,ImageDraw,ImageColor
import time
import pHash

#身份匹配
def comp_faces(faceImgs,faceImg, size=(32,32),part_size=(8,8)):
    min_code = 1000 
    for key in faceImgs:
        code = pHash.classify_DCT(faceImgs[key],faceImg, size,part_size)
        print(key,' : ',code)
        if code < min_code:
            min_code = code
            uname = key
    if min_code > 20:
        return "Who am I ?"
    else:
        return "I'm " + uname

#人脸识别
def detectFaces(image_path, ispath=1):
    if ispath == 1:
        img = cv2.imread(image_path)
    else:
        img = image_path

    #face_cascade = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml")
    face_cascade = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml")
    if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        gray = img 

    #faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(10,10), flags=cv2.CASCADE_SCALE_IMAGE)
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(30,30), flags=cv2.CASCADE_SCALE_IMAGE)
    #detectMultiScale(args)
    # 2.scaleFactor 每次图像尺寸减小的比例,尺度越大,越容易漏掉检测的对象,但检测速度加快;尺度越小,检测越细致准确
    # 3.minNeighbors 表示每一个目标至少要被检测到3次才算是真的目标
    # 4.minSize 目标的最小尺寸
    # 5.maxSize 目标的最大尺寸
    return faces

def get_faces():
    every_faces = {}
    for image_file in glob.glob('pic/face/*_face.jpg'):
        spx = image_file.split('_')[0].split('/')
        spxLen = len(spx) - 1
        every_faces[spx[spxLen]] = Image.open(image_file)
    return every_faces

def get_cam(todo, faceImg='', times=0):
    if todo == 'cface':
        every_face1 = get_faces()

    # 从摄像头中取得视频
    cap = cv2.VideoCapture(0) 
    # 获取视频播放界面长宽
    #width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) + 0.5)
    #height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) + 0.5)
    # 定义编码器 创建 VideoWriter 对象
    #fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Be sure to use the lower case
    #out = cv2.VideoWriter('pic/output.mp4', fourcc, 20.0, (width, height))

    #头像标注
    show_txt = 'Scan...'
    sec = 0
    while(cap.isOpened()):
        if todo == 'gface':
            sec = int(time.time()) - times
            show_txt = 'Scan...' + str(sec)
        #读取帧摄像头
        ret, frame = cap.read()
        if ret == True:
            #输出当前帧
            #out.write(frame)
            faces = detectFaces(frame, 0)
            #获取头像
            if todo == 'gface' and os.path.exists(faceImg)!=True:
                if len(faces) == 1:
                    if sec>=5:
                        todo = ''
                        for (x, y, w, h) in faces:
                            #cropped = frame[y-180:y+h+80, x-50:x+w+50]
                            cropped = frame[y:y+h, x:x+w]
                            cv2.imwrite(faceImg, cropped)
                            #cv2.imshow("ImgShow", cropped)
                            show_txt = 'Scan Success !'
                else:
                    show_txt = 'Too many people !'
            for (x, y, w, h) in faces:
                #识别头像
                if todo == 'cface':
                    #OpenCV_data=np.asarray(PIL_data)
                    #cam_face = Image.fromarray(cam_face_x)
                    cropped = frame[y:y+h, x:x+w]
                    frameImg = Image.fromarray(cropped)
                    show_txt = comp_faces(every_face1, frameImg)
                #标注头像
                cv2.rectangle(frame, (x,y),(x+w, y+h), (0, 255, 0), 2)
                font = cv2.FONT_HERSHEY_COMPLEX
                cv2.putText(frame,show_txt, (x,y), font, 1, (255,255,255), 2, cv2.LINE_AA)
            cv2.imshow('Camera Test',frame)
            #键盘 q 退出
            if (cv2.waitKey(1) & 0xFF) == ord('q'):
                break
        else:
            break
    
    # 释放资源
    #out.release()
    cap.release()
    cv2.destroyAllWindows()
    
__all__ = [get_cam]

if __name__ == '__main__':
    times = int(time.time())
    #get_cam('cface')
    #get_cam('gface', 'pic/face/'+sys.argv[2]+'_face.jpg', times)
    try:
        todo = sys.argv[1]
        if todo == 'gface':
            if len(sys.argv) != 3:
                raise Exception()
            get_cam('gface', 'pic/face/'+sys.argv[2]+'_face.jpg', times)
        if todo == 'cface':
            get_cam('cface')
    except Exception as e:
        print('Usage:')
        print('   采集面部身份')
        print(' - $main.py gface face-username')
        print('   面部身份识别')
        print(' - $main.py cface')