5150浏览
查看: 5150|回复: 4

【行空板】AI跟随摄像头

[复制链接]
本帖最后由 云天 于 2022-5-23 21:36 编辑

【行空板】AI跟随摄像头图2【行空板】AI跟随摄像头图4【行空板】AI跟随摄像头图3

【项目设计】
已经掌握了行控板与micro:bit扩展板的结合的使用方法,那么扩展板上的舵机引脚就可以驱动摄像头云台。
Mediapipe获取人脸中心坐标,通过滤波算法使用得数据不频繁抖动。通过PID算法,控制舵机运行,追踪人脸。
【控制舵机】
microbit_motor.py文件可从Pinpong库中找到,上传到行空板中,应与主文件在同一个文件夹内。
【行空板】AI跟随摄像头图5

  1. # -*- coding: utf-8 -*-
  2. import time
  3. from pinpong.board import Board
  4. from microbit_motor import Microbit_Motor #导入Microbit_Motor库
  5. Board("microbit").begin()  #初始化,选择板型和端口号,不输入端口号则进行自动识别
  6. #Board("microbit","COM36").begin()  #windows下指定端口初始化
  7. #Board("microbit","/dev/ttyACM0").begin()   #linux下指定端口初始化
  8. #Board("microbit","/dev/cu.usbmodem14101").begin()   #mac下指定端口初始化
  9. motorbit = Microbit_Motor()
  10. while True:
  11.    #舵机引脚S1-S8,角度范围0-180
  12.    motorbit.servo(motorbit.S2, 0)
  13.    time.sleep(1)
  14.    motorbit.servo(motorbit.S2, 90)
  15.    time.sleep(1)
  16.    motorbit.servo(motorbit.S2, 180)
  17.    time.sleep(1)
  18.    motorbit.servo(motorbit.S2, 90)
  19.    time.sleep(1)
复制代码

【行空板】AI跟随摄像头图6

【行空板获取摄像头全屏】在行空板网页端使用Jupyter notebook,在终端使用:pip install cvzone,安装cvzone
  1. import cvzone.FaceDetectionModule as face
  2. import cv2
  3. import numpy as np
  4. import time
  5. def main():
  6.     cap = cv2.VideoCapture(0)
  7.     cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
  8.     cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
  9.     cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
  10.     cv2.namedWindow('camera',cv2.WND_PROP_FULLSCREEN)    #窗口全屏
  11.     cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)   #窗口全屏
  12.     detector = face.FaceDetector()
  13.     # For a 640x480 image center target is 320 and 240
  14.     while True:
  15.         success, img = cap.read()
  16.         img, bboxs = detector.findFaces(img)
  17.         if bboxs:
  18.             x, y, w, h = bboxs[0]["bbox"]
  19.             cx, cy = bboxs[0]["center"]
  20.             xVal=cx
  21.             yVal=cy
  22.             cv2.putText(img, f'x:{xVal} , y:{yVal} ', (x, y - 100), cv2.FONT_HERSHEY_PLAIN, 3,
  23.                         (255, 0, 0), 3)
  24.         output_image = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
  25.         cv2.imshow("camera", output_image)
  26.         cv2.waitKey(1)
  27. if __name__ == "__main__":
  28.     main()
复制代码

【人脸中心数据滤波】
使用的是“递推平均滤波法”:
递推平均滤波法(又称滑动平均滤波法
方法:  把连续取N个采样值看成一个队列,遵循先进先出原则  队列的长度固定为N  每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)  把队列中的N个数据进行算术平均运算,就可获得新的滤波结果  N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4
优点:  对周期性干扰有良好的抑制作用,平滑度高  适用于高频振荡的系统
缺点:  灵敏度低  对偶然出现的脉冲性干扰的抑制作用较差  不易消除由于脉冲干扰所引起的采样值偏差  不适用于脉冲干扰比较严重的场合  比较浪费RAM  

  1. import cvzone.FaceDetectionModule as face
  2. import cv2
  3. import numpy as np
  4. import time
  5. def main():
  6.     cap = cv2.VideoCapture(0)
  7.     #cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
  8.     #cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
  9.     #cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
  10.     #cv2.namedWindow('camera',cv2.WND_PROP_FULLSCREEN)    #窗口全屏
  11.     #cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)   #窗口全屏
  12.     detector = face.FaceDetector()
  13.     s=[0,0,0,0,0,0,0,0,0,0,0,0]
  14.     while True:
  15.         PTime = time.time()
  16.         success, img = cap.read()
  17.         img, bboxs = detector.findFaces(img)
  18.         if bboxs:
  19.             x, y, w, h = bboxs[0]["bbox"]
  20.             cx, cy = bboxs[0]["center"]
  21.             xVal=cx
  22.             yVal=cy
  23.             cv2.putText(img, f'x:{xVal} , y:{yVal} ', (x, y - 100), cv2.FONT_HERSHEY_PLAIN, 3,
  24.                         (255, 0, 0), 3)
  25.         #output_image = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
  26.             s.pop(0)
  27.             s.append(cx)
  28.             mean=int(np.mean(s))
  29.             cv2.putText(img, f'x:{mean} , y:{yVal} ', (x, y - 50), cv2.FONT_HERSHEY_PLAIN, 3,
  30.                         (255, 0, 0), 3)
  31.         fps = 1 / (time.time() - PTime)
  32.         cv2.putText(img, f'FPS: {int(fps)}', (20,50), cv2.FONT_HERSHEY_PLAIN,
  33.                             3, (255, 255, 0), 3)
  34.         cv2.imshow("camera", img)
  35.         cv2.waitKey(1)
  36.         
  37. if __name__ == "__main__":
  38.     main()
复制代码

【行空板】AI跟随摄像头图7
【PID控制水平舵机】

  1. import cvzone.FaceDetectionModule as face
  2. import cv2
  3. import numpy as np
  4. import time
  5. from pinpong.board import Board
  6. from microbit_motor import Microbit_Motor #导入Microbit_Motor库
  7. Board("microbit").begin()
  8. motorbit = Microbit_Motor()
  9. targetVal=0
  10. pError=0
  11. pTime=0
  12. pidVals=[0.03,0,0.01]
  13. I=0
  14. jd_x=90
  15. def pid(cVal):
  16.         global I,pidVals,pTime,pError,targetVal
  17.         # Current Value - Target Value
  18.         t = time.time() - pTime
  19.         error = cVal - targetVal
  20.         P = pidVals[0] * error
  21.         I = I + (pidVals[1] * error * t)
  22.         D = (pidVals[2] * (error - pError)) / t
  23.         result = P + I + D
  24.         
  25.         pError = error
  26.         ptime = time.time()
  27.         return result
  28. def main():
  29.     global ptime,jd_x
  30.     cap = cv2.VideoCapture(0)
  31.     cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
  32.     cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
  33.     cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
  34.     cv2.namedWindow('camera',cv2.WND_PROP_FULLSCREEN)    #窗口全屏
  35.     cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)   #窗口全屏
  36.     detector = face.FaceDetector()
  37.     s=[0,0,0,0,0,0]
  38.     ptime = time.time()
  39.     motorbit.servo(motorbit.S2,jd_x)
  40.     pre_jd_x=0
  41.     while True:
  42.         PTime = time.time()
  43.         success, img = cap.read()
  44.         img, bboxs = detector.findFaces(img)
  45.         if bboxs:
  46.             x, y, w, h = bboxs[0]["bbox"]
  47.             cx, cy = bboxs[0]["center"]
  48.             xVal=cx
  49.             yVal=cy
  50.             cv2.putText(img, f'x:{xVal} , y:{yVal} ', (x, y - 100), cv2.FONT_HERSHEY_PLAIN, 3,
  51.                         (255, 0, 0), 3)
  52.         
  53.             s.pop(0)
  54.             s.append(cx)
  55.             mean=int(np.mean(s))
  56.             jd_x=jd_x+int(pid(160-mean))
  57.             if jd_x<1:
  58.                 jd_x=1
  59.             if jd_x>179:
  60.                 jd_x=179
  61.             print(jd_x)
  62.             if pre_jd_x !=jd_x:
  63.               pre_jd_x =jd_x
  64.               motorbit.servo(motorbit.S2,jd_x)
  65.             cv2.putText(img, f'x:{mean} , y:{yVal} ', (x, y - 50), cv2.FONT_HERSHEY_PLAIN, 3,
  66.                         (255, 0, 0), 3)
  67.         fps = 1 / (time.time() - PTime)
  68.         cv2.putText(img, f'FPS: {int(fps)}', (20,50), cv2.FONT_HERSHEY_PLAIN,
  69.                             3, (255, 255, 0), 3)
  70.         output_image = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)                    
  71.         cv2.imshow("camera", output_image)
  72.         cv2.waitKey(1)
  73.         
  74. if __name__ == "__main__":
  75.     main()
复制代码

【使用PID类控制水平】
  1. import cvzone.FaceDetectionModule as face
  2. import cv2
  3. import numpy as np
  4. import time
  5. from pinpong.board import Board
  6. from microbit_motor import Microbit_Motor #导入Microbit_Motor库
  7. Board("microbit").begin()
  8. motorbit = Microbit_Motor()
  9. targetVal=0
  10. pError=0
  11. pTime=0
  12. pidVals=[0.03,0,0.01]
  13. I=0
  14. jd_x=90
  15. class PID:
  16.     def __init__(self, pidVals, targetVal,  limit=None):
  17.         self.pidVals = pidVals
  18.         self.targetVal = targetVal
  19.         self.pError = 0
  20.         self.limit = limit
  21.         self.I = 0
  22.         self.pTime = 0
  23.     def update(self,cVal):
  24.         
  25.         # Current Value - Target Value
  26.         t = time.time() - self.pTime
  27.         error = cVal - self.targetVal
  28.         P = self.pidVals[0] * error
  29.         self.I = self.I + (self.pidVals[1] * error * t)
  30.         D = (self.pidVals[2] * (error - self.pError)) / t
  31.         result = P + self.I + D
  32.         if self.limit is not None:
  33.             result = float(np.clip(result, self.limit[0], self.limit[1]))
  34.         
  35.         self.pError = error
  36.         self.ptime = time.time()
  37.         return result
  38. def main():
  39.    
  40.     cap = cv2.VideoCapture(0)
  41.     cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
  42.     cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
  43.     cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
  44.     cv2.namedWindow('camera',cv2.WND_PROP_FULLSCREEN)    #窗口全屏
  45.     cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)   #窗口全屏
  46.     detector = face.FaceDetector()
  47.     s_x=[0,0,0,0,0,0]
  48.     jd_x=90
  49.     pre_jd_x=0
  50.     motorbit.servo(motorbit.S2,jd_x)
  51.     xPID = PID([0.03, 0.000000000001, 0.01], 320 // 2,  limit=[-90, 90])
  52.     while True:
  53.         PTime = time.time()
  54.         success, img = cap.read()
  55.         img, bboxs = detector.findFaces(img)
  56.         if bboxs:
  57.             x, y, w, h = bboxs[0]["bbox"]
  58.             cx, cy = bboxs[0]["center"]
  59.             xVal=cx
  60.             yVal=cy
  61.             cv2.putText(img, f'x:{xVal} , y:{yVal} ', (x, y - 100), cv2.FONT_HERSHEY_PLAIN, 3,
  62.                         (255, 0, 0), 3)
  63.         
  64.             s_x.pop(0)
  65.             s_x.append(cx)
  66.             mean_x=int(np.mean(s_x))
  67.             
  68.             xVal= int(xPID.update(mean_x))
  69.             jd_x=jd_x-xVal
  70.             print(jd_x)
  71.             if pre_jd_x !=jd_x:
  72.               pre_jd_x =jd_x
  73.               motorbit.servo(motorbit.S2,jd_x)
  74.             cv2.putText(img, f'x:{mean_x} , y:{yVal} ', (x, y - 50), cv2.FONT_HERSHEY_PLAIN, 3,
  75.                         (255, 0, 0), 3)
  76.         fps = 1 / (time.time() - PTime)
  77.         cv2.putText(img, f'FPS: {int(fps)}', (20,50), cv2.FONT_HERSHEY_PLAIN,
  78.                             3, (255, 255, 0), 3)
  79.         output_image = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)                    
  80.         cv2.imshow("camera", output_image)
  81.         cv2.waitKey(1)
  82.         
  83. if __name__ == "__main__":
  84.     main()
复制代码
控制水平和垂直舵机
  1. import cvzone.FaceDetectionModule as face
  2. import cv2
  3. import numpy as np
  4. import time
  5. from pinpong.board import Board
  6. from microbit_motor import Microbit_Motor #导入Microbit_Motor库
  7. Board("microbit").begin()
  8. motorbit = Microbit_Motor()
  9. targetVal=0
  10. pError=0
  11. pTime=0
  12. pidVals=[0.03,0,0.01]
  13. I=0
  14. jd_x=90
  15. class PID:
  16.     def __init__(self, pidVals, targetVal,  limit=None):
  17.         self.pidVals = pidVals
  18.         self.targetVal = targetVal
  19.         self.pError = 0
  20.         self.limit = limit
  21.         self.I = 0
  22.         self.pTime = 0
  23.     def update(self,cVal):
  24.         
  25.         # Current Value - Target Value
  26.         t = time.time() - self.pTime
  27.         error = cVal - self.targetVal
  28.         P = self.pidVals[0] * error
  29.         self.I = self.I + (self.pidVals[1] * error * t)
  30.         D = (self.pidVals[2] * (error - self.pError)) / t
  31.         result = P + I + D
  32.         if self.limit is not None:
  33.             result = float(np.clip(result, self.limit[0], self.limit[1]))
  34.         
  35.         self.pError = error
  36.         self.ptime = time.time()
  37.         return result
  38. def main():
  39.    
  40.     cap = cv2.VideoCapture(0)
  41.     cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
  42.     cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
  43.     cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
  44.     cv2.namedWindow('camera',cv2.WND_PROP_FULLSCREEN)    #窗口全屏
  45.     cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)   #窗口全屏
  46.     detector = face.FaceDetector()
  47.     s_x=[0,0,0,0,0,0]
  48.     s_y=[0,0,0,0,0,0]
  49.     jd_x=90
  50.     jd_y=135
  51.     pre_jd_y=0
  52.     motorbit.servo(motorbit.S1,jd_y)
  53.     xPID = PID([0.03, 0.000000000001, 0.01], 320 // 2,  limit=[-90, 90])
  54.     yPID = PID([0.03, 0.000000000001, 0.01], 240 // 2,  limit=[-45, 45])
  55.     while True:
  56.         PTime = time.time()
  57.         success, img = cap.read()
  58.         img, bboxs = detector.findFaces(img)
  59.         if bboxs:
  60.             x, y, w, h = bboxs[0]["bbox"]
  61.             cx, cy = bboxs[0]["center"]
  62.             xVal=cx
  63.             yVal=cy
  64.             cv2.putText(img, f'x:{xVal} , y:{yVal} ', (x, y - 100), cv2.FONT_HERSHEY_PLAIN, 3,
  65.                         (255, 0, 0), 3)
  66.         
  67.             s_x.pop(0)
  68.             s_y.pop(0)
  69.             s_x.append(cx)
  70.             s_y.append(cy)
  71.             mean_x=int(np.mean(s_x))
  72.             mean_y=int(np.mean(s_y))
  73.             xVal= int(xPID.update(mean_x))
  74.             yVal= int(yPID.update(mean_y))
  75.             jd_x=jd_x-xVal
  76.             jd_y=jd_y-yVal
  77.             print(jd_x,jd_y)
  78.             if pre_jd_x !=jd_x:
  79.               pre_jd_x =jd_x
  80.               motorbit.servo(motorbit.S2,jd_x)
  81.             if pre_jd_y !=jd_y:
  82.               pre_jd_y =jd_y
  83.               motorbit.servo(motorbit.S1,jd_y)
  84.             cv2.putText(img, f'x:{mean_x} , y:{mean_y} ', (x, y - 50), cv2.FONT_HERSHEY_PLAIN, 3,
  85.                         (255, 0, 0), 3)
  86.         fps = 1 / (time.time() - PTime)
  87.         cv2.putText(img, f'FPS: {int(fps)}', (20,50), cv2.FONT_HERSHEY_PLAIN,
  88.                             3, (255, 255, 0), 3)
  89.         output_image = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)                    
  90.         cv2.imshow("camera", output_image)
  91.         cv2.waitKey(1)
  92.         
  93. if __name__ == "__main__":
  94.     main()
复制代码
【行空板】AI跟随摄像头图1
【演示视频】


白凡  高级技师

发表于 2022-9-8 20:21:17

试了下,行空板连接microBIT扩展板贼好用!学到了!谢谢!
回复

使用道具 举报

cdx8002  学徒

发表于 2022-12-2 21:51:05

能获得XY的坐标数据,能获得Z轴角度吗,或是,眼睛的水平角度。就是头的侧倾斜角度。陈德新 cdx777777
回复

使用道具 举报

QaQ  见习技师

发表于 2023-2-8 15:19:00

二哈识图是个好东西
回复

使用道具 举报

曾剑波  初级技匠

发表于 2023-11-30 17:36:23

看着不错!我也来搞搞
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail