【手势识别小车】---------(3)人脸识别

血一般的教训,整这个东西,代码没用多久,但是配环境真的把人快整吐了,这里先把踩过的坑和解决方法在这里说一下…

博主的环境: Ubuntu18.04+Pycharm

大一的时候实验室要求学习Tensorflow,又接手了学长们的一个项目,负责视觉方面的东西,水平不够学的一知半解,电脑上下载了一大堆库,一大堆环境,各种版本的环境交错融杂,文件夹胡乱摆放在犄角旮旯,这导致我电脑的环境非常凌乱,我自己没有概念,后面也没有删这些乱七八糟的东西,这种行为为此时的我埋下了无数恶果…
问题是从一个函数开始的:

recognizer = cv2.face.LBPHFaceRecognizer_create()

这句代码疯狂给我报错

module 'cv2' has no attribute 'face'

浏览国内外各种网站,试过了所有的解决方法,无外乎就是安装一个叫opencv-contrib-python的拓展包,face是这个包里面的函数,

pip install opencv-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install opencv-contrib-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install opencv-contrib-python-headless -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

按理说安好了这个拓展包,该函数就能用了,但我仍然报错,在磕了三四天无果后,决定彻底把cv2删掉重新配环境,首先使用指令

pip uninstall opencv-python
pip uninstall opencv-contrib-python
pip uninstall opencv-python-headless

以及检查了【手势识别小车】---------(3)人脸识别

这里面,确定是删掉了,可是当我把鼠标移到代码中的import cv2,发现仍然可以点开,此时意识到是环境中仍然存在cv2路径。于是我进入到cv2的源码,发现了这个opencv来源于曾经安装的openvino,删除openvino后,彻底清除掉了环境中所有的opencv,再按上述方法安装后便成功了。
但是又出现了新的问题,就是cv2库中的函数无法自动补全,但是可以正常运行,至今未能解决…有办法的朋友可以私信我一下万分感谢!

环境配好了接下来就是人脸识别部分了,博主使用了两种方法

方法一. 调用face_recognition人脸识别库

识别人脸,如果不在人脸库,则可以选择是否加入人脸库

# -*- coding=UTF-8 -*-
import cv2
import os
import face_recognition
import numpy as np
import sys
cap = cv2.VideoCapture(0)

new = '/home/bj/PycharmProjects/facefound/drivers'  #存照片的地方
Know_face_encodings = []
Know_face_names = []
face_locations = []
face_encodings = []
face_names = []
filelist = os.listdir(new)
process_this_frame = True
def add_Driver():
    print("welcome to here ,new driver")
    print("please input your name,and look at the camare,it will take photos after 3s:")
    i = input(":")
    ret, frame = cap.read()
    cv2.imshow('cap', frame)
    output_path = os.path.join(new, "%s.jpg" % i)
    cv2.imwrite(output_path, frame)
    out = face_recognition.load_image_file(output_path)
    out_encoding = face_recognition.face_encodings(out)[0]
    Know_face_encodings.append(out_encoding)
    Know_face_names.append(i)

for i in filelist:
    # creat arrays of record face name
    img_path = os.path.join('drivers', "%s" % i)
    image = face_recognition.load_image_file(img_path)
    img_encoding = face_recognition.face_encodings(image)[0]
    Know_face_encodings.append(img_encoding)
    Know_face_names.append(i)
#Initialize some variables
while True:
    ret, frame = cap.read()
    flag = cv2.waitKey(1)
    #Resize video's size to receive faster
    small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

#turn BGR to RGB color
    rgb_small_frame = small_frame[:, :, ::-1]
    if process_this_frame:
        #Find all face and faceencodings to contract
        face_locations = face_recognition.face_locations(rgb_small_frame,model="cnn")
        face_encodings = face_recognition.face_encodings(rgb_small_frame,face_locations)
        face_names=[]
        for face_encoding in face_encodings:
            #see if the face match the face we knowen
            matchs = face_recognition.compare_faces(Know_face_encodings,face_encoding)在这里插入代码片
            name = "Unknown"
            # print("if you want to join us,push 'o':")
            # if flag==13 :
            #     add_Driver()
            # else:
                #if we find the same face
                #name =we knownface
            face_distances = face_recognition.face_distance(Know_face_encodings,face_encoding)
            best_match_index = np.argmin(face_distances)
            print(best_match_index)
            if matchs[best_match_index]:
                name = Know_face_names[best_match_index]
            if best_match_index == 0:
                while(1):
                    print("do you want to join in?")
                    a=input()
                    if a == 'y':
                        add_Driver()
                        break
                    if a == 'n':
                        break

            face_names.append(name)
    process_this_frame = not process_this_frame

    #display the results
    for (top, right, bottom, left), name in zip(face_locations, face_names):
        top *= 4
        right *= 4
        bottom *= 4
        left *= 4
    #Draw a box around face
        cv2.rectangle(frame, (left-10, top-100), (right+10, bottom+50), (0, 0, 225), 2)
    #Draw a label with a name below the face
        cv2.rectangle(frame, (left-10, bottom+15), (right+10, bottom+50), (0, 0, 255), cv2.FILLED)
        #set zi ti
        font = cv2.FONT_HERSHEY_DUPLEX
        cv2.putText(frame, name, (left+6, bottom+44), font, 1.0, (255, 255, 255),1)
    cv2.imshow('cap', frame)
    if flag == 27:
        break
cap.release()
cv2.destroyAllWindows()

方法二:LBPHFaceRecognizer直方图识别法

1.创建人脸库,采集50张当前摄像头识别的人脸照片做素材

# -*- coding=UTF-8 -*-
import os
import sys
import numpy
import cv2
cap = cv2.VideoCapture(0)
face_detector = cv2.CascadeClassifier(r'/home/bj/PycharmProjects/FACE/haarcascade_frontalface_default.xml')
drivers_id = input('write down your name:')
path = '/home/bj/PycharmProjects/FACE/drivers'
if not os.path.exists(path+'/'+drivers_id):
    os.makedirs(path+'/'+drivers_id)
count = 0
while True:
    success, img = cap.read()
    if success is True:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        break
    faces = face_detector.detectMultiScale(gray, 1.3, 5)
    for(x, y, w, h) in faces:
        flag = cv2.waitKey(1)
        cv2.rectangle(img, (x-500, y-500), (x+w+500, y+w+500), (225, 0, 0))
        count += 1
        thepath = os.path.join('drivers', drivers_id, "%s" % drivers_id)
        cv2.imwrite(thepath+ str(count) + '.jpg', gray[y:y+h, x:x+w])
        if flag == 27:
            break
        elif count>=50:
            cap.release()
            cv2.destroyAllWindows()
            break
        cv2.imshow('image', img)



2.训练人脸模型

# -*-coding:utf-8-*-
import cv2
import os
import numpy as np
def face_detect(image):
    gray = cv2.cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    face_detector = cv2.CascadeClassifier("/home/bj/PycharmProjects/FACE/haarcascade_frontalface_default.xml")
    faces = face_detector.detectMultiScale(gray, 1.2, 6)
    if(len(faces)==0):
        return None, None
    (x, y, w, h) = faces[0]
    return gray[y:y+w, x:x+h], faces[0]
def ReFileName(dirPath):
    print(os.listdir(dirPath))
    faces = []
    for file in os.listdir(dirPath):
        print(file)
        if os.path.isfile(os.path.join(dirPath, file)) == True:
            c = os.path.basename(file)
            name = dirPath + '/' +c
            img = cv2.imread(name)
            face, rect = face_detect(img)
            if face is not None:
                faces.append(face)
    cv2.waitKey(1)
    cv2.destroyAllWindows()

    return faces
dirPathslx = r"drivers/slx"
slx = ReFileName(dirPathslx)
print(len(slx))
lableslx = np.array([0 for i in range(len(slx))])
dirPathyg = r"drivers/yg"
yg = ReFileName(dirPathyg)
print(len(yg))
lableyg = np.array([1 for i in range(len(yg))])
x = np.concatenate((slx, yg), axis=0)
y = np.concatenate((lableslx, lableyg), axis=0)
index = [i for i in range(len(y))]
np.random.seed(1)
np.random.shuffle(index)
train_data = x[index]
train_label = y[index]
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(train_data, train_label)
# 保存训练数据
recognizer.write('train.yml')

3.实时识别当前摄像头人脸

# -*-coding:utf-8-*-
import cv2
cap = cv2.VideoCapture(0)
face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
facelabel = ["slx", "yg"]#人物名
#人脸检测函数
def face_detect_demo(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    faces = face_detector.detectMultiScale(gray, 1.2, 6)
    # 如果未检测到面部,则返回原始图像
    if (len(faces) == 0):
        return None, None
    # 目前假设只有一张脸,xy为左上角坐标,wh为矩形的宽高
    (x, y, w, h) = faces[0]
    # 返回图像的脸部部分
    return gray[y:y + w, x:x + h], faces[0]


#导入训练结果
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('train.yml')#读取前文训练的结果


# 根据给定的人脸(x,y)坐标和宽度高度在图像上绘制矩形
def draw_rectangle(img, rect):
    (x, y, w, h) = rect#矩形框
    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)

# 根据给定的人脸(x,y)坐标写出人名
def draw_text(img, text, x, y):
    cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)

# 此函数识别图像中的人物并在脸部周围绘制一个矩形及其人名

def predict(image):
    # 生成图像的副本,保留原始图像
    # 检测人脸区域
    face, rect = face_detect_demo(img)#face_detect_demo前面的人脸检测函数
    #print(rect)=[x,y,w,h]
    # 预测人脸名字
    label = recognizer.predict(face)
    print(label)#label[0]为名字,label[1]可信度数值越低,可信度越高(
    if label[1]<=70:
        # 获取由人脸识别器返回的相应标签的人名
        label_text = facelabel[label[0]]

        # 在检测到的脸部周围画一个矩形
        draw_rectangle(img, rect)
        # 标出预测的人名
        draw_text(img, label_text, rect[0], rect[1])
        # 返回预测的图像
        return img
    else:
        # 在检测到的脸部周围画一个矩形
        draw_rectangle(img, rect)
        # 标出预测的人名
        draw_text(img, "not find", rect[0], rect[1])
        # 返回预测的图像
        return img
while True:
    success, img = cap.read()
    if success is True:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        break
    faces = face_detector.detectMultiScale(gray, 1.3, 5)
    for (x, y, w, h) in faces:
        flag = cv2.waitKey(1)
        cv2.rectangle(img, (x - 500, y - 500), (x + w + 500, y + w + 500), (225, 0, 0))
        cv2.imwrite(str(1) + '.jpg', gray[y:y + h, x:x + w])
        if flag == 27:
            exit()
        cv2.imshow('image', img)
#执行预测
        pred_img = predict('1.jpg')
        cv2.imshow('result', pred_img)
        if flag == 27:
            break
cv2.waitKey(0)
cv2.destroyAllWindows()

各个部分功能实现后,我开始把它们汇总,最终代码如下

上一篇:浅谈虚拟环境管理工具virtualenvwrapper


下一篇:netty系列之:使用netty实现支持http2的服务器