使用Opencv+树莓派实现人脸识别(一)图片人脸检测和摄像头人脸捕捉

前置安装

我的树莓派是3b,就1G内存,系统为stretch版本,自带的python为3.5版本
强烈建议在烧写树莓派系统时就直接用buster版本,自带的python版本在3.7及以上
Windows下直接使用PyCharm安装python-opencv,python-opencv-contrib,pyqt5,pyqt5-tools

树莓派下编译安装OpenCV:十分困难,可能要编译4-5小时

树莓派上python3已经可以直接使用pip包管理来直接安装OpenCV

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install libhdf5-dev libhdf5-serial-dev
sudo apt-get install libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5
sudo apt-get install libatlas-base-dev
sudo apt-get install libjasper-dev
sudo pip3 install --no-cache-dir opencv-contrib-python==3.4.3.18

检测是否安装成功:

python3 test.py
import cv2
print(cv2.__version__)

这里我们直接在Windows使用PyCharm写代码,然后通过FileZilla传输到树莓派运行

静态图片检测

灰度化

度化处理就是将一幅彩色图像转化为灰度图像的过程

当R=G=B=255时,灰度值达到最高,显示为白色,反之则显示为黑色。

图像灰度化的目的是为了简化矩阵

彩色图像中的每个像素颜色由R、G、B三个分量来决定,而每个分量的取值范围都在0-255之间,这样对计算机来说,彩色图像的一个像素点就会有16777216种颜色的变化范围

而灰度图像是R、G、B分量相同的一种特殊彩色图像,对计算机来说,一个像素点的变化范围只有0-255这256种

使用到的特征分类器

Haar特征分类器,其实就是一个XML文件,用于描述人体各个部位的Haar特征值(眼睛,嘴唇等)

引用一个博客的说法:(42条消息) 机器学习 之 Haar特征_苏的专栏-CSDN博客

Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征。它分为三类:边缘特征、线性特征、中心特征和对角线特征。用黑白两种矩形框组合成特征模板,在特征模板内用 黑色矩形像素和 减去 白色矩形像素和来表示这个模版的特征值。例如:脸部的一些特征能由矩形模块差值特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述在特定方向(水平、垂直、对角)上有明显像素模块梯度变化的图像结构。

在安装目录可以找到分类器文件,从文件名就能大致看出其功能

使用Opencv+树莓派实现人脸识别(一)图片人脸检测和摄像头人脸捕捉

#detectMultiScale函数可以检测处图片中的所有人脸   ( 识别图像中的人脸,返回所有人脸的矩形框向量组 )
#且可以使用向量(vector)将所有人脸的坐标大小(矩形表示)保存
# scaleFactor 为了检测到不同大小的目标,通过scalefactor参数把图像长宽同时按照一定比例(默认1.1)逐步缩小,
# 然后检测,这个参数设置的越大,计算速度越快,但可能会错过了某个大小的人脸。
# minNeighbors 构成检测目标的相邻矩形的最小个数,默认值是3
faces = haar_face_cascade.detectMultiScale(gray_img, scaleFactor=1.1,minNeighbors=3)
cv2.rectangle(image, start_point, end_point, color, thickness)

image:它是要在其上绘制矩形的图像。
start_point:它是矩形的起始坐标。坐标表示为两个值的元组,即(X坐标值,Y坐标值)。
end_point:它是矩形的结束坐标。坐标表示为两个值的元组,即(X坐标值ÿ坐标值)。
color:它是要绘制的矩形的边界线的颜色。对于BGR,我们通过一个元组。例如:(255,0,0)为蓝色。
thickness:它是矩形边框线的粗细像素。厚度-1像素将以指定的颜色填充矩形形状

静态检测代码

import cv2
import numpy as np

def dection(imagepath):
    image = cv2.imread(imagepath,cv2.IMREAD_COLOR) #读取图片
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#图像灰度化,用于简化矩阵运算
    face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')  # xml来源于资源文件。
    faces = face_cascade.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=1)
    for (x , y, w, h) in faces:
            image = cv2.rectangle(image, (x, y) , (x+w , y+h) , (0,0,255) , 2)
    cv2.namedWindow('face')
    cv2.imshow('face',image)
    cv2.waitKey(0)  #等待退出键
    cv2.destroyAllWindows()


dection('img2.jpg')

用摄像头做检测(此时仍然是简单的检测,并非识别,大抵上只是将图像源换为了摄像头的图像帧)

.pgm格式

Portable Gray Map

灰度图像格式中一种最简单的格式标准。另外两种与之相近的图片格式是PBM和PPM。它们分别相应着黑白图像和彩色图像

使用Opencv+树莓派实现人脸识别(一)图片人脸检测和摄像头人脸捕捉

camera.read()函数

read()函数返回一个bool类型,表示帧的读取的正确与否(可以用来检查视频文件是否到达结尾)

(read之前可以使用isOpened()来检测是否成功初始化摄像头

如果初始化false,则使用open()

read():

参数ret 为True 或者False,代表有没有读取到图片 第二个参数frame表示截取到一帧的图片

用一个死循环一直读取摄像头帧,每读到一帧就检测一次

import cv2
import numpy as np

def det(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    faces = face_detector.detectMultiScale(gray, 1.2, 6)
    for x, y, w, h in faces:
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
    cv2.imshow("result", image)
#视频检测人脸
def video_detc():
    camera = cv2.VideoCapture(1)#打开摄像头(插入usb摄像头后,0为笔记本摄像头,1为usb摄像头)
    while(True):
        ret, frame = camera.read()
        frame = cv2.flip(frame, 1)#设置个镜像(好看一点)
        det(frame)
        c = cv2.waitKey(10)
        if c == 27: # ESC
            break
video_detc()

人脸识别数据集的录入

使用pgm格式存储

让用户自己输入id(用于修改文件名,区分不同人的数据集)

例如某一个人录入的pgm文件名全为:User_1.pam,1即为用户输入的id

使用Opencv+树莓派实现人脸识别(一)图片人脸检测和摄像头人脸捕捉

使用Opencv+树莓派实现人脸识别(一)图片人脸检测和摄像头人脸捕捉

#一个id(一个人)录入50-100张图片,这里选了100张(可能在检测的时候精度更高)
#并且保存为pgm格式
#需要去手动设置你的人脸id值
import cv2
import os
def input_face_data():
    camera = cv2.VideoCapture(1)
    #使用默认大小
    face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    id = input("请输入id,并回车:")
    print("请正视摄像头,多做几个表情")
    pic_count = 0 #记录有多少pgm文件
    while(True):
        ret,frame = camera.read()
        frame = cv2.flip(frame, 1)  # 设置个镜像(好看一点)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_detector.detectMultiScale(gray, 1.2, 6)
        for (x,y,w,h) in faces:
            pic_count+=1
            cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
            cv2.imwrite("D:\\py_study\\facedetection\\dataset\\User_"+str(id)+"_"+str(pic_count)+".pgm",gray[y:y+h,x:x+w])
            cv2.imshow('image', frame)
            print("录入第"+str(pic_count)+"张结束")
            k = cv2.waitKey(100) & 0xff  # Press 'ESC' for exiting video
        c = cv2.waitKey(10)
        if c == 27:  # ESC
            break
        elif pic_count>=100:
            print("结束录入数据集")
            break

input_face_data()

上一篇:opencv 读取相机图像+ros发布图像


下一篇:将私人画廊送进千家万户,三星The Frame电视全球累计总销量将超200万台