这里给大家带来一个借助角蜂鸟实现的人脸检测控制的机器人。
硬件清单参考如下:
- 角蜂鸟
- 树莓派3b
- 奥松机器人
- 12V转5V的DC-DC模块(可选)
- 散热风扇(可选)
在角蜂鸟内置的模型中,为我们提供了 Mobilenet-SSD
模型,我们将使用这个模型实现人脸检测的功能。大概的处理逻辑如下:
首先组装好奥松机器人,奥松机器人为树莓派供电,树莓派为角蜂鸟供电,树莓派通过USB通信控制奥松机器人和角蜂鸟。 由于树莓派USB供电限制,可能会产生供电不足的问题,影响稳定性。这里考虑从奥松机器人的电源上接入12V转5V的DC-DC模块为USB提供额外供电,或者使用外源HUB。 担心空间散热性比较差可考虑加入散热风扇。
为了优雅与美观,这里我们DIY了奥松机器人,把所有的东西都埋进了脑袋里,角蜂鸟放在了后脑勺的位置。
奥松机器人控制代码如下:
class RapiroProcessor(Thread):
class Flags:
face = None
face_frame_cnt = 0
head_angle = 90
arm_raised = False
light_on = False
light_need_change = False
def __init__(self, connection):
Thread.__init__(self)
self.daemon = True
self.rapiro = Rapiro(connection)
self.flags = RapiroProcessor.Flags()
def reset(self):
self.rapiro.execute(GO_TO_INITIAL_POSITION)
time.sleep(3)
def run(self):
self.reset()
try:
while True:
time.sleep(0.1)
has_face = self.flags.face is not None
frame_cnt = self.flags.face_frame_cnt
comm = ""
if has_face: # 计算头部舵机角度
x1 = self.flags.face[2]
x2 = self.flags.face[4]
x_mid = (x1 + x2) / 2
if x_mid > 0.6 or x_mid / 2 < 0.4:
angle = self.flags.head_angle - int((x_mid - 0.5) / 0.1)
else:
angle = self.flags.head_angle
angle = 180 if angle > 180 else angle
angle = 0 if angle < 0 else angle
self.flags.head_angle = angle
eye = (246, 124, 1)
frame_cnt += 1
else:
eye = (2, 220, 255)
frame_cnt -= 1
self.flags.light_need_change = (not has_face if self.flags.light_on else has_face)
self.flags.light_on = has_face
if frame_cnt > 5: # 举起右手
self.flags.face_frame_cnt = 5
if not self.flags.arm_raised:
comm += r_shoulder_yz(90, 1)
self.flags.arm_raised = True
elif frame_cnt < -5: # 放下右手
self.flags.face_frame_cnt = -5
if self.flags.arm_raised:
comm += r_shoulder_yz(0, 1)
self.flags.arm_raised = False
else:
self.flags.face_frame_cnt = frame_cnt
if self.flags.light_need_change: # 眼睛变色
comm += eye_color(eye[0], eye[1], eye[2], 1)
comm += head_yaw(self.flags.head_angle, 1)
self.rapiro.execute(comm)
finally:
self.reset()
角蜂鸟处理逻辑如下:
#!/usr/bin/env python3
# coding=utf-8
import sys
sys.path.append("../../SungemSDK-Python")
import hsapi as hs
import rapiro
import video
def process(ret):
img = ret[0]
face = []
img_w = img.shape[1]
img_h = img.shape[0]
for box in ret[1]:
if (box[4] - box[2] > img_w * 0.8) \
and (box[5] - box[3] > img_h * 0.8):
# 过滤网络误检
continue
box[2] /= img_w
box[4] /= img_w
box[3] /= img_h
box[5] /= img_h
face.append(box)
return face
if __name__ == '__main__':
t_rapiro = rapiro.RapiroProcessor("/dev/ttyUSB0") # 控制线程
t_video = video.VideoProcessor(("192.168.50.202", 10600)) # 视频线程
try:
net = hs.FaceDetector(zoom=True, verbose=0, threshSSD=0.55)
t_rapiro.start()
t_video.start()
while True:
result = net.run()
image = net.plot(result)
faces = process(result)
t_rapiro.flags.face = faces[0] if len(faces) > 0 else None
if t_video.has_client():
t_video.input_queue.put(image) # 传输视频到远端
finally:
t_rapiro.reset()
当检测到人脸时,奥松机器人的头部会跟随转动,保持人脸在视野居中位置,举起右手,同时眼睛变为黄色;当检测不到人脸时,手臂放下,同时眼睛变为蓝色。