成果展示:
如下视频所示为制作好的人脸跟踪电风扇
人脸跟踪风扇
相关代码已经放在百度网盘上面了。
链接:https://pan.baidu.com/s/188AylEd2QgOiA6YFv01N3A
提取码:e2og
主要原理
其主要原理就是,摄像头对风扇前面的内容进行预览,树莓派对摄像头拍到的画面进行实时的检测,检测出人脸的位置。然后根据位置来控制云台的转动,从而达到风扇始终对着人脸的目标。
原理示意图:
树莓派通过检测人脸位置,大致判断人脸相对自己的位置,然后转换成角度,控制云台运动。
代码编写:
这里主要看一下最重要的代码,就是在获取到一帧图像之后的处理流程,我把它放在slot_camera方法中
1 def slot_camera(self):
2 if (self.cap.isOpened()):
3 self.frame += 1
4 # get a frame
5 ret, img = self.cap.read()
6 height, width, bytesPerComponent = img.shape
7 bytesPerLine = bytesPerComponent * width
8
9 if self.frame % 1 == 0:
10 image_p = img.ctypes.data_as(ctypes.c_char_p)
11 self.alg_handle.alg_run.restype = ctypes.POINTER(ctypes.c_float)
12 result = self.alg_handle.alg_run(image_p, 11, height, width, 4)
13
14 # cls
15 if int(result[0]) == 0:
16 pass
17 # det
18 elif int(result[0]) == 1:
19 box_count = int(result[1])
20 for j in range(box_count):
21 cls = int(result[2 + j * 6 + 0])
22 prob = float(result[2 + j * 6 + 1])
23 if prob < 0.4:
24 continue
25 x1 = int(float(result[2 + j * 6 + 2]) * width)
26 y1 = int(float(result[2 + j * 6 + 3]) * height)
27 x2 = int(float(result[2 + j * 6 + 4]) * width)
28 y2 = int(float(result[2 + j * 6 + 5]) * height)
29 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 1)
30 x_center = (float(result[2 + j * 6 + 2]) + float(result[2 + j * 6 + 4])) / 2
31 y_center = (float(result[2 + j * 6 + 3]) + float(result[2 + j * 6 + 5])) / 2
32 x_angle = int((x_center - 0.5) * 40 / 0.5)
33 y_angle = int((y_center - 0.5) * 40 / 0.5)
34 self.servo_cmd['x_dir'] = 'left' if x_angle <= 0 else 'right'
35 self.servo_cmd['x_angle'] = abs(x_angle)
36
37 cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)
38 cv2.putText(img, 'x:%s %d'%( self.servo_cmd['x_dir'], self.servo_cmd['x_angle']), (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 2)
39 ServoControl('x', self.servo_cmd['x_dir'], self.servo_cmd['x_angle'])
40
41 self.image = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888)
42 self.label_frame.setPixmap(QPixmap.fromImage(self.image).scaled(self.label_frame.width(), self.label_frame.height()))
43
44