发帖人:搞点板子
树莓派宠物机器人项目大联大友尚安森美USB双目摄像头分系统功能今天将完成最后功能 识别人脸并识别出家庭成员,然后根据成员显示名字和反馈出声音,并且追踪人脸进行移动运动追踪。 一通过尚安森美USB双目摄像头结合opencv识别出家庭成员 在上一次测试4中,通过采集家庭成员的人脸,对树莓派的opencv进行了训练并生成了训练文件trainer.yml 现在就利用这个文件进行识别。 在这里还要安装一个opencv识别依赖库 pip3 install pillow 使用 LBPH(LOCAL BINARY PATTERNSHISTOGRAMS)人脸识别器, | recognizer = cv2.face.LBPHFaceRecognizer_create() |
函数「ge timagesAndLabels (path)」将抽取所有在目录「dataset/」中的照片,并返回 2 个数组:「Ids」和「faces」。通过将这些数组作为输入,我们就可以训练识别器。 | recognizer.train(faces, ids) |
我们接下来要设置一个名字数组来匹配之前采集数据照片时候的数字ID names = ['dage', 'who', 'baba'],摄像头识别出后会显示匹配的名字。 代码如下: import cv2 import numpy as np import os recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read('trainer/trainer.yml') cascadePath ="haarcascade_frontalface_default.xml" faceCascade = cv2.CascadeClassifier(cascadePath); font = cv2.FONT_HERSHEY_SIMPLEX #iniciate id counter id = 0 # names related to ids: example ==> Marcelo:id=1, etc names = ['dage', 'who', 'baba'] # Initialize and start realtime video capture cam = cv2.VideoCapture(0) cam.set(3, 640) # set video widht cam.set(4, 480) # set video height # Define min window size to be recognized as a face minW = 0.1*cam.get(3) minH = 0.1*cam.get(4) while True: ret, img=cam.read() img =cv2.flip(img, 1) # Flip vertically gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) faces =faceCascade.detectMultiScale( gray, scaleFactor= 1.2, minNeighbors = 5, minSize =(int(minW), int(minH)), ) for(x,y,w,h) infaces: cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2) id,confidence = recognizer.predict(gray[y:y+h,x:x+w]) # Check ifconfidence is less them 100 ==> "0" is perfect match if(confidence < 100): id =names[id] confidence = " {0}%".format(round(100 - confidence)) else: id ="unknown" confidence = " {0}%".format(round(100 - confidence)) cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2) cv2.putText(img,str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1) cv2.imshow('camera',img) k =cv2.waitKey(10) & 0xff # Press 'ESC' for exiting video if k == 27: break # Do a bit of cleanup print("n [INFO] Exiting Program and cleanupstuff") cam.release() cv2.destroyAllWindows() 虽然识别的数据少,但是我戴眼镜之后的还是会识别出来,并给予一个百分比进行判断。opencv的功能还是非常强大的,他是通过人的眼睛和嘴巴来进行更进一步的识别和对比的。 会在相似的人脸之间不断的识别切换的。 二尚安森美USB双目摄像头结合opencv追踪人脸移动小车及大联大友尚安森美摄像头持续追踪人脸 当追踪到识别的家庭成员人脸后以图片的中心位置为参考,根据人脸和人的运动调整宠物小车和USB摄像进行移动和追踪确保摄像头捕捉人像的中心位置的同时,摄像头会随着宠物小车转向保持追踪。 这部分硬件调试问题较多,软件完成并可以输出驱动板所需数据,借助网上的资料进行了程序的调试。 使用树莓派的GPIO 11,12,13,15 引脚连接L298n驱动器的in1,in2,in3,in4 输入口,通过步进机驱动的out1,out2,out3,out4输出口控制步进电机的前进转向和后退。 import RPi.GPIO as GPIO #引入RPi.GPIO库函数命名为GPIO import time #引入计时time函数 # BOARD编号方式,基于插座引脚编号 GPIO.setmode(GPIO.BOARD) #将GPIO编程方式设置为BOARD模式 #接口定义 INT1 = 11 #将L298 INT1口连接到树莓派Pin11 INT2 = 12 #将L298 INT2口连接到树莓派Pin12 INT3 = 13 #将L298 INT3口连接到树莓派Pin13 INT4 = 15 #将L298 INT4口连接到树莓派Pin15 #输出模式 GPIO.setup(INT1,GPIO.OUT) GPIO.setup(INT2,GPIO.OUT) GPIO.setup(INT3,GPIO.OUT) GPIO.setup(INT4,GPIO.OUT) GPIO.output(INT1,GPIO.HIGH) GPIO.output(INT2,GPIO.LOW) GPIO.output(INT3,GPIO.HIGH) GPIO.output(INT4,GPIO.LOW) GPIO.cleanup() 通过opencv识别出人脸在USB摄像头中的坐标。根据坐标计算数值传输给驱动板和舵机。 import cv2 # 开始读取摄像头信号 cap = cv2.VideoCapture(0) # 当读取到信号时 while cap.isOpened(): # 读取每一帧视频图像为frame (ret, frame) =cap.read() # 将颜色空间转换为hsv hsv =cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 指定目标颜色的下限 yellow_lower =(26, 43, 46) # 指定目标颜色的上限 yellow_upper =(34, 255, 255) # 使用目标范围分割图像并二值化 mask =cv2.inRange(hsv, yellow_lower, yellow_upper) # 寻找其中的所有外轮廓 (mask, cnts,hierarchy) = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 如果至少找到一个轮廓 if len(cnts)> 0: # 找出其中面积最大的轮廓 c =max(cnts, key=cv2.contourArea) # 分析轮廓的中心位置和大小 ((x, y),radius) = cv2.minEnclosingCircle(c) # 如果半径大于50 if radius> 50: print("中心坐标", (x, y)) 接下来要控制小车转向使得摄像头中X坐标接近320 并调整舵机转向移动,完成小车移动追踪人脸的目的。 import serial #导入调用串口的python第三方包serial import cv2 #导入OpenCV包 import time #导入time包 from robotic ARM import get_message #导入控制机械臂所必须的get_message函数 #声明一个变量,表示轴1舵机的pwm值 pwm1 = 1500 ser = serial.Serial("/dev/ttyAMA0", 9600) #初始化树莓派的 通信串口 #机械臂位置初始化 ser.write(get_message(1, 1500, 4)) ser.write(get_message(2, 1500, 4)) ser.write(get_message(3, 1500, 4)) time.sleep(2) #等待舵机执行完成 #识别黄色木块的坐标位置 cap = cv2.VideoCapture(0) count = 0 #计数 while cap.isOpened(): (ret, frame) =cap.read() if count <=60: #计数小于等于60时 count += 1#count自增1 continue #跳过后面的语句,继续循环 hsv =cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) yellow_lower =(26, 43, 46) yellow_upper =(34, 255, 255) mask =cv2.inRange(hsv, yellow_lower, yellow_upper) (mask, cnts,hierarchy) = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if len(cnts)> 0: c =max(cnts, key=cv2.contourArea) ((x, y),radius) = cv2.minEnclosingCircle(c) if radius> 50: print("center: ", (x, y)) #根据坐标调整机械臂运动 if x> 330: pwm1 += int((x - 320) / 10 + 5) elif x< 310: pwm1 -= int((320 - x) / 10 + 5) ser.write(get_message(1, pwm1, 4)) 三树莓派对宠物小车的控制,使用尚安森美USB双目摄像头结合opencv追踪人脸并播放对应音频 接下来要进行的是识别出特定人脸后播放对应的音频进行互动和反馈响应的,原打算计划使用大联大友尚的语音控制模块进行结合互动开发的,但是,一直没能完全的公开语音模组,没有完整这部分功能,只能进行识别后反馈音频。 目前只完成了代码测试,硬件及宠物小车的测试还有待完善。 以下代码结合上面的移动代码进行了整合声音的输出。 该部分代码也是参考了很多网络上的开源项目进行了测试。 import cv2 import serial from roboticarm import get_message import face_recognition import time import pygame.mixer as player from threading import Thread #初始化pygame播放器 player.init(frequency=44100) #自定义播放音频的函数,参数为音频文件地址 def playaudio(address): Sound =player.Sound(address) Sound.play() while True: if not player.get_busy(): break #设定线程t1、t2,功能分别为播放找到人脸和丢失人脸时的音频 t1 = Thread(target = playaudio, args =["/home/pi/audios/1.wav"]) t2 = Thread(target = playaudio, args =["/home/pi/audios/2.wav"]) #载入包含你面部的图片并对它编码 my_image = cv2.imread("/home/pi/photos/1.jpg") my_image = cv2.cvtColor(my_image, cv2.COLOR_BGR2RGB) my_face_encoding =face_recognition.face_encodings(my_image) ser = serial.Serial("/dev/ttyAMA0", 9600) #初始化串口 #用两个变量记录两个舵机的pwm值 pwm1 = 1500 pwm2 = 1500 #令云台转动到初始位置 ser.write(get_message(1, pwm1, 40)) ser.write(get_message(2, pwm2, 40)) stage = 0 #程序流程变量,0表示识别,1表示追踪 get_face = False #表示当前是否找到人脸 start_time = time.time() #记录最近一次丢失人脸的时间信息 face_cascade =cv2.CascadeClassifier('/home/pi/cascade/haarcascade_frontalface_default.xml') #载入人脸分类器 cap = cv2.VideoCapture(0) #开始读取摄像头信号 while cap.isOpened(): (ret, frame) =cap.read() #读取每一帧视频图像为frame frame =cv2.flip(frame, 0) #将图像上下镜像翻转 gray =cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #将图像转换为灰度图 faces =face_cascade.detectMultiScale(gray, minSize=(100, 100),flags=cv2.CASCADE_FIND_BIGGEST_OBJECT) #检测人脸的位置 if stage == 0:#若处于识别阶段 face_locations = [] #定义一个列表存储人脸的位置信息 for (left,top, width, height) in faces: #遍历找到的人脸的位置信息 #计算出右下角的坐标 right = left + width bottom= top + height #为face_locations添加一个人脸的位置信息,注意需要强制转换为int类型 face_locations.append((int(top), int(right), int(bottom), int(left))) rgb_frame =cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) #得到每一帧的rgb图像信息 face_encodings = face_recognition.face_encodings(rgb_frame,face_locations) #计算特定位置的人脸特征信息 forface_encoding in face_encodings: #遍历得到的所有人脸特征信息 matches= face_recognition.compare_faces(my_face_encoding, face_encoding,tolerance=0.5) #比较它与已知的人脸 if Truein matches: #如果检测成功 stage = 1 #进入追踪阶段 get_face = True #改变get_face的取值 elif stage ==1: #若处于追踪阶段 if len(faces)> 0: #如果寻找到人脸 #如果此前get_face为False,说明找到了人脸,如果距离上次丢失人脸超过5秒,则播放音频 if notget_face and time.time() - start_time > 5: #只有当前未播放任何音频时才播放 if(not t1.isAlive()) and (not t2.is_alive()): t1.start() get_face = True #改变get_face的取值 else: #如果没有找到人脸 ifget_face: #若上一帧找到了人脸,更新start_time取值 start_time = time.time() #若连续几秒未找到人脸,令舵机复位,播放丢失人脸的音频并回到识别阶段 iftime.time() - start_time > 5: if(not t1.isAlive()) and (not t2.is_alive()): t2.start() pwm1 = 1500 pwm2 = 1500 stage = 0 get_face = False #改变get_face的取值 for (left,top, width, height) in faces: #遍历找到的人脸的位置信息 #计算出人脸位置中心点的坐标 x0 =left + width / 2 y0 =top + height / 2 #比较坐标与中心点的差别,调整舵机的pwm值 if x0> 330: pwm1 += (x0 - 320) / 6 elif x0< 310: pwm1 -= (320 - x0) / 6 if y0> 250: pwm2 += (y0 - 240) / 6 elif y0< 230: pwm2 -= (240 - y0) / 6 #指令舵机转向 ser.write(get_message(1,pwm1, 40)) ser.write(get_message(2, pwm2, 40)) cap.release() ser.close() 至此最后,基于大联大友尚安森美 半导体感光芯片USB双目摄像头模组的智能宠物小车项目摄像头识别追踪就全部完成了。 该项目过程中,历经了很多的挫折和坑,主要是,win10和树莓派移植之间耽误了很多时间,opencv的编译安装过程浪费的一些时间。由于原计划中参与项目的硬件较多,造成该项目时断时停。 本次测试中,大联大友尚安森美半导体感光芯片USB双目摄像头模组起到了很大作用,该模组对于各种光环境下的人脸识别和追踪有很大帮助, 摄像头的清晰度和颜色调节对于分辨指定人脸有很大的帮助和支持。 再次感谢大联大友尚安森美和发烧友,efans小助手给予的支持和帮助。 本文,第二,和三部分由于硬件调试问题,从网络上找了很多资料完成了项目剩余的测试。
|