[项目]行空板视觉循迹车 精华

29587浏览
查看: 29587|回复: 0

[项目] 行空板视觉循迹车

[复制链接]
【项目背景】
之前,有个网友咨询用行空板做视觉循迹车,我做了一个,给这个网友参考。之后这个车就被再“利用”了,今天再重新做一个。
【项目设计】
在佳立创重新打板,实现固定电机及电机驱动板。这个板子是为给micro:bit设计的小车底板,因行空行板也可使用这个电机驱动板,并且Mind+中Python模式下已有这个电机驱动板的扩展。
【佳立创打板】
电路比较简单,设置好布局和尺寸。
行空板视觉循迹车图7


行空板视觉循迹车图3

【组装小车】
电机驱动板使用3.7V锂电池供电。
行空板视觉循迹车图1


行空板视觉循迹车图2


行空板视觉循迹车图6

【程序编写】
Mind+ Python模式下连接行空板编写程序。
行空板视觉循迹车图8
1.测试驱动电机使用pinpong库加载“DFMotor”驱动电机。
  1. #  -*- coding: UTF-8 -*-
  2. # MindPlus
  3. # Python
  4. import time
  5. from pinpong.board import Board
  6. from pinpong.libs.microbit_motor import DFMotor
  7. Board().begin()
  8. p_dfr0548_motor_M1 = DFMotor(1)
  9. p_dfr0548_motor_M2 = DFMotor(2)
  10. p_dfr0548_motor_M3 = DFMotor(3)
  11. p_dfr0548_motor_M4 = DFMotor(4)
  12. p_dfr0548_motor_ALL = DFMotor(5)
  13. while True:
  14.     p_dfr0548_motor_M1.speed(200)
  15.     p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CCW)
  16.     p_dfr0548_motor_M2.speed(200)
  17.     p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CCW)
  18.     p_dfr0548_motor_M3.speed(200)
  19.     p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CCW)
  20.     p_dfr0548_motor_M4.speed(200)
  21.     p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CCW)
  22.     time.sleep(2)
  23.     p_dfr0548_motor_ALL.stop()
  24.     time.sleep(2)
复制代码


2.行空板 Opencv 视频 识线加载opencv 库函数头文件”cv2“,开启USB摄像头采集图像,通过图像处理,获取目标颜色,进而识别目标”线“所在区域。
  1. import cv2            # opencv 库函数头文件引用
  2. import numpy as np    # python 库引用
  3. import math           # python 库引用
  4. import sys
  5. class Twist:   
  6.     x = 0
  7.     z = 0
  8.     linear=0
  9.     angular=0
  10. # 利用opencv 库函数,从摄像头采集一帧图像
  11. cap = cv2.VideoCapture(0)
  12. ret, cv_image = cap.read()
  13. while ret:  
  14.    ret, cv_image = cap.read()
  15.    # 对图像进行裁剪
  16.    height, width, channels = cv_image.shape
  17.    descentre = 50
  18.    rows_to_watch = 100
  19.    crop_img = cv_image[(int((height)/4) + descentre):(int((height)/4)+ (descentre+rows_to_watch))][1:width]
  20.    #将图像从RGB转换成HSV色彩空间
  21.    hsv = cv2.cvtColor(crop_img,cv2.COLOR_RGB2HSV)
  22.    # 设置需要提取的颜色的是绿色,然后确认其HSV空间下的范围
  23.    lower = np.array([0,0,5])
  24.    upper = np.array([180,255,100])
  25.    #制作模板,绿色部分和其他颜色二值化后变为白色和黑色
  26.    mask = cv2.inRange(hsv,lower ,upper)
  27.    #将模板图像和原始图像按照 像素 位相与,提取出目标颜色
  28.    res = cv2.bitwise_and(crop_img,crop_img,mask = mask)
  29.    m = cv2.moments(mask,False)
  30.    try:
  31.         cx, cy = m['m10']/m['m00'], m['m01']/m['m00']
  32.    except ZeroDivisionError:
  33.         cx, cy = height/2, width/2
  34.    height, width, channels = cv_image.shape
  35.    error_x = cx - width / 2
  36.    twist_object = Twist()
  37.    # 设置固定的线速度值,单位 m/s
  38.    twist_object.linear = 0.05
  39.    # 将横向像素的偏差除以一个系数,该系数决定角速度值的大小,需要根据线速度和图像总宽度进行调节,才能达到比较好的循迹效果
  40.    twist_object.angular = error_x / 80
  41. # 二值化图像的像素统计,即统计目标颜色区域所占的像素个数
  42.    no_red = cv2.countNonZero(mask)
  43.    # 添加角速度和目标颜色像素判别,避免过大的角速度出现,防止车疯狂旋转
  44.    if ((math.fabs(twist_object.angular)) < 10 and (no_red > 20000)):
  45.         print(twist_object.angular)
  46.    else:
  47.       twist_object.linear = 0
  48.       print("out of range")
  49.       twist_object.angular = 0
  50.    cv2.imshow("dst",mask)
  51.    if cv2.waitKey(1) & 0xff== 27:
  52.        break
复制代码


3.完整程序
  1. import cv2            # opencv 库函数头文件引用
  2. import numpy as np    # python 库引用
  3. import math           # python 库引用
  4. import sys
  5. import time
  6. from pinpong.board import Board
  7. from pinpong.libs.microbit_motor import DFMotor
  8. Board().begin()
  9. p_dfr0548_motor_M1 = DFMotor(1)
  10. p_dfr0548_motor_M2 = DFMotor(2)
  11. p_dfr0548_motor_M3 = DFMotor(3)
  12. p_dfr0548_motor_M4 = DFMotor(4)
  13. p_dfr0548_motor_ALL = DFMotor(5)
  14. def speed(left,right):
  15.     p_dfr0548_motor_M1.speed(left)
  16.     p_dfr0548_motor_M1.run(p_dfr0548_motor_M1.CW)
  17.     p_dfr0548_motor_M2.speed(left)
  18.     p_dfr0548_motor_M2.run(p_dfr0548_motor_M2.CW)
  19.     p_dfr0548_motor_M3.speed(right)
  20.     p_dfr0548_motor_M3.run(p_dfr0548_motor_M3.CW)
  21.     p_dfr0548_motor_M4.speed(right)
  22.     p_dfr0548_motor_M4.run(p_dfr0548_motor_M4.CW)
  23. def numberMap(x, in_min, in_max, out_min, out_max):
  24.   return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
  25. num=30#电机启动基数
  26. num2=100#电机调整范围
  27. class Twist:   
  28.     x = 0
  29.     z = 0
  30.     linear=0
  31.     angular=0
  32. # 利用opencv 库函数,从摄像头采集一帧图像
  33. cap = cv2.VideoCapture(0)
  34. ret, cv_image = cap.read()
  35. while ret:  
  36.    ret, cv_image = cap.read()
  37.    # 对图像进行裁剪
  38.    height, width, channels = cv_image.shape
  39.    descentre = 50
  40.    rows_to_watch = 100
  41.    crop_img = cv_image[(int((height)/4) + descentre):(int((height)/4)+ (descentre+rows_to_watch))][1:width]
  42.    #将图像从RGB转换成HSV色彩空间
  43.    hsv = cv2.cvtColor(crop_img,cv2.COLOR_RGB2HSV)
  44.    # 设置需要提取的颜色的是绿色,然后确认其HSV空间下的范围
  45.    lower = np.array([0,0,5])
  46.    upper = np.array([180,255,100])
  47.    #制作模板,绿色部分和其他颜色二值化后变为白色和黑色
  48.    mask = cv2.inRange(hsv,lower ,upper)
  49.    #将模板图像和原始图像按照 像素 位相与,提取出目标颜色
  50.    res = cv2.bitwise_and(crop_img,crop_img,mask = mask)
  51.    m = cv2.moments(mask,False)
  52.    try:
  53.         cx, cy = m['m10']/m['m00'], m['m01']/m['m00']
  54.    except ZeroDivisionError:
  55.         cx, cy = height/2, width/2
  56.    height, width, channels = cv_image.shape
  57.    error_x = cx - width / 2
  58.    twist_object = Twist()
  59.    # 设置固定的线速度值,单位 m/s
  60.    twist_object.linear = 0.05
  61.    # 将横向像素的偏差除以一个系数,该系数决定角速度值的大小,需要根据线速度和图像总宽度进行调节,才能达到比较好的循迹效果
  62.    twist_object.angular = error_x / 80
  63. # 二值化图像的像素统计,即统计目标颜色区域所占的像素个数
  64.    no_red = cv2.countNonZero(mask)
  65.    # 添加角速度和目标颜色像素判别,避免过大的角速度出现,防止车疯狂旋转
  66.    if ((math.fabs(twist_object.angular)) < 10 and (no_red > 20000)):
  67.         print(twist_object.angular)
  68.         if(twist_object.angular>0):
  69.            left=int(numberMap(int(twist_object.angular*100),0,300,0,num2))
  70.            print("left:"+str(left))
  71.            speed(num-left,num+left)
  72.         if(twist_object.angular<0):
  73.            right=int(numberMap(int(abs(twist_object.angular)*100),0,300,0,num2))
  74.            print("right:"+str(right))
  75.            speed(num+right,num-right)
  76.    else:
  77.       twist_object.linear = 0
  78.       print("out of range")
  79.       twist_object.angular = 0
  80.    #cv2.imshow("dst",mask)
  81.    #if cv2.waitKey(1) & 0xff== 27:
  82.        #break
复制代码

行空板视觉循迹车图5


行空板视觉循迹车图4

【演示视频】




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

本版积分规则

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

硬件清单

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

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

mail