前置安装
我的树莓派是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特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征。它分为三类:边缘特征、线性特征、中心特征和对角线特征。用黑白两种矩形框组合成特征模板,在特征模板内用 黑色矩形像素和 减去 白色矩形像素和来表示这个模版的特征值。例如:脸部的一些特征能由矩形模块差值特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述在特定方向(水平、垂直、对角)上有明显像素模块梯度变化的图像结构。
在安装目录可以找到分类器文件,从文件名就能大致看出其功能
#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。它们分别相应着黑白图像和彩色图像
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
#一个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()