1.树莓派3B+。
2.树莓派原装csi接口摄像头。(也可使用usb摄像头)
1.安装ubuntu mata 18.04 for 树莓派。
安装过程可参考此链接:树莓派ubuntu mate安装
另外附上ubuntumate官网:ubuntu mate官网
2.安装完成后还需要进行一些基础配置。
(1).使能csi摄像头。
sudo apt update
sudo apt upgrade
sudo apt-get install raspi-config
sudo raspi-config
重启树莓派后:
sudo vim /etc/modules
打开文件在最后添加一行(这样才能将树莓派sci摄像头设置为video 0设备,以便opencv调用)
bcm2835-v4l2
完成后使用下方这句,如出现摄像头图像显示则恭喜你配置成功!
raspivid -o mykeychain.h264 -t 10000 -w 1280 -h 720
1.安装python3.6:
参考以下链接:python3.6安装
2.安装pip3环境:
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
3.安装opencv
参考的是以下链接安装opencv:opencv pip安装
全部安装完成后进行测试:
python3
import cv2
如果不报错说明安装完成!
1.首先写两个函数,分别实现人脸识别和画框标记功能。
def get_faces(img):#人脸识别函数,传入读取到的图片
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#灰度化处理
faces=face_cascade.detectMultiScale(gray,
scaleFactor=1.5,#此值越小,检测出来的可疑目标越多
minNeighbors=4,
minSize=(20,20))#最小检测目标像素大小
return faces,img,gray
def draw_frame(faces,img,gray):
for (x,y,w,h) in faces:#遍历faces列表中的元素
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)#画框框
cv2.imshow("video",img)#图像显示
以上两段代码为基础检测与标记处理。
然而由于树莓派运算能力的问题,如果不采用特殊处理,画面帧率只有几帧,远不能满足我们的要求。所以需采用多线程及跳帧处理的方法来提高帧率。
以下代码为多线程及跳帧实现:
pool = mp.Pool( processes=2 )#创建多线程,线程数为2(也可以使用4线程)
read, img = camera.read()#从摄像头读取一帧图像
pr1 = pool.apply_async( get_faces, [ img ] )#将这帧图像提交给线程1
read, img = camera.read()#从摄像头读取一帧图像
pr2 = pool.apply_async( get_faces, [ img ] )#将这帧图像提交给线程2
#read, img = camera.read()
#pr3 = pool.apply_async( get_faces, [ img ] )
#read, img = camera.read()
#pr4 = pool.apply_async( get_faces, [ img ] )
fcount=1 #线程控制变量
jump=1 #跳帧控制变量
while True:#进入循环
read,img=camera.read()
if jump%2==0: #当是偶数帧的时候才去处理
if fcount == 1: #线程1工作
pr1 = pool.apply_async( get_faces, [ img ] ) #将这帧图像提交给线程1
faces, img, gray=pr2.get() #获取线程2的结果
draw_frame( faces, img, gray ) #标记框位置
elif fcount == 2: #线程2工作
pr2 = pool.apply_async( get_faces, [ img ] ) #将这帧图像提交给线程2
faces, img, gray=pr1.get()#获取线程1的结果
draw_frame( faces, img, gray )#标记框位置
fcount=0
#elif fcount == 3:
# pr3 = pool.apply_async( get_faces, [ img ] )
# faces, img, gray=pr4.get()
# draw_frame( faces, img, gray )
#elif fcount == 4:
# pr4 = pool.apply_async( get_faces, [ img ] )
# faces, img, gray=pr1.get()
# draw_frame( faces, img, gray )
# fcount = 0
fcount += 1
jump=jump+1
if jump>29:
jump=0
c=cv2.waitKey(1)
if c==27: #按下键盘Esc键退出
cv2.destroyAllWindows()
break
完整代码如下:
import cv2
import multiprocessing as mp
import os
import time
face_cascade=cv2.CascadeClassifier('/home/yhk/cvfile/people.xml')
def get_faces(img):
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces=face_cascade.detectMultiScale(gray,
scaleFactor=1.5,
minNeighbors=4,
minSize=(20,20))
return faces,img,gray
def draw_frame(faces,img,gray):
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("video",img)
################################程序开始#######
camera= cv2.VideoCapture(0)
#camera.set(3,480)
#camera.set(4,320)
pool = mp.Pool( processes=2 )
read, img = camera.read()
pr1 = pool.apply_async( get_faces, [ img ] )
read, img = camera.read()
pr2 = pool.apply_async( get_faces, [ img ] )
#read, img = camera.read()
#pr3 = pool.apply_async( get_faces, [ img ] )
#read, img = camera.read()
#pr4 = pool.apply_async( get_faces, [ img ] )
fcount=1
jump=1
while True:
read,img=camera.read()
if jump%2==0:
if fcount == 1:
pr1 = pool.apply_async( get_faces, [ img ] )
faces, img, gray=pr2.get()
draw_frame( faces, img, gray )
elif fcount == 2:
pr2 = pool.apply_async( get_faces, [ img ] )
faces, img, gray=pr1.get()
draw_frame( faces, img, gray )
fcount=0
#elif fcount == 3:
# pr3 = pool.apply_async( get_faces, [ img ] )
# faces, img, gray=pr4.get()
# draw_frame( faces, img, gray )
#elif fcount == 4:
# pr4 = pool.apply_async( get_faces, [ img ] )
# faces, img, gray=pr1.get()
# draw_frame( faces, img, gray )
# fcount = 0
fcount += 1
jump=jump+1
if jump>29:
jump=0
c=cv2.waitKey(1)
if c==27:
cv2.destroyAllWindows()
break
最终效果:识别较为准确,帧率尚可。基本满足要求。
期间参考了很多博主大牛,希望分享出来帮助大家!