工训赛——智能救援01

一.目的

写这篇文章记录自己在打工训赛的时候遇到的问题以及解决方案,为以后自己的复习留下文章

二.智能救援项目

1.项目介绍

        智能救援项目是在一块方向区域内,两辆全自动小车实现自动寻找目标,到达位置,抓取目标,将目标放置在规定区域。

2.大体思路

        通过摄像头找到小球的位置,识别颜色,获取坐标,这里的坐标是小球在屏幕上的位置以及小球的半径,还需要进行计算获取小球关于小车的位置,当获取小球关于小车位置之后,将信号发送给小车,小车到达目标位置,抓取小球,再进行识别兑换区域,当到达后将小球放置其中即可。

        难点:

                1.如何精确识别小球,并获取其位置

                2.如何识别兑换区域

三.技术实现

1.识别不同颜色的小球

思路:

HSV处理
        1.通过将图片转化为HSV格式

        hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

        2.将HSV三通道分离

        h, s, v = cv2.split(hsv)

        3.通过调整HSV三通道,各个通道阈值,使得想要出现的颜色最明显

        h_binary = cv2.inRange(np.array(h), np.array(hmin), np.array(hmax))

        s_binary = cv2.inRange(np.array(s), np.array(smin), np.array(smax))

        v_binary = cv2.inRange(np.array(v), np.array(vmin), np.array(vmax))

        4.将三通道合并

        binary = cv2.bitwise_and(h_binary, cv2.bitwise_and(s_binary, v_binary))

到这里完成了基本的处理,将不同颜色的球分开

这里需要对于每个颜色调整,重新运行程序十分费劲,滑动条实时调整比较方便一些
        1.初始化窗口

        cv2.namedWindow('h_binary')

        cv2.namedWindow('s_binary')

        cv2.namedWindow('v_binary')

        2.创建轨迹条

        cv2.createTrackbar('hmin', 'h_binary', 6, 179, nothing)

        cv2.createTrackbar('hmax', 'h_binary', 26, 179, nothing)

        cv2.createTrackbar('smin', 's_binary', 110, 255, nothing)

        cv2.createTrackbar('smax', 's_binary', 255, 255, nothing)

        cv2.createTrackbar('vmin', 'v_binary', 140, 255, nothing)

        cv2.createTrackbar('vmax', 'v_binary', 255, 255, nothing)

        参数

parameter1:滑动条名称

parameter2:添加到哪个窗口

parameter3:滑动条初始值

parameter4:滑动条最大值(最小值为0)

        3.获取轨迹条的值

        hmin = cv2.getTrackbarPos('hmin', 'h_binary')

        hmax = cv2.getTrackbarPos('hmax', 'h_binary')

        smin = cv2.getTrackbarPos('smin', 's_binary')

        smax = cv2.getTrackbarPos('smax', 's_binary')

        vmin = cv2.getTrackbarPos('vmin', 'v_binary')

        vmax = cv2.getTrackbarPos('vmax', 'v_binary')

cv2.getTrackbarPos() 是回调函数,获取的是之前创建的轨迹条的值

当我把轨迹条的值一直在循环中赋值给合并前的通道最大值以及最小值,即可实时返回更改后的图像,及时观察图片变化

图片预处理

        1.高斯滤波

        blur = cv2.GaussianBlur(binary, (13, 13), 0)

        2.创建卷积核  

        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))

        3.开运算(开运算能够除去孤立的小点,毛刺和小桥,而总的位置和形状不变)

        Open = cv2.morphologyEx(blur, cv2.MORPH_OPEN, kernel)

        4.闭运算(闭运算能够填平小孔,弥合小裂缝,而总的位置和形状不变)

        Close = cv2.morphologyEx(Open, cv2.MORPH_CLOSE, kernel)

圆形检测

圆形检测这里有很多方法,上次去工训只是实验了霍夫圆检测,但霍夫圆检测也存在很多缺陷,用起来很抖

        霍夫圆检测

        circles = cv2.HoughCircles(Close, cv2.HOUGH_GRADIENT, 2, 20, param1=200,         param2=50, minRadius=1, maxRadius=300)

这里会返回数组circles,一个或多个圆形的x,y,r,还有可能没有检测到

画图

        1.先判断是否检测到了圆

        2.先将circles四舍五入,再转化为uint16型(因为像素没有小数)

        3.对circles进行遍历

        4.给出圆心以及半径画圆,以及圆心

    if type(circles) != type(None):     #防止没有找到圆形轮廓

        circles = np.uint16(np.around(circles))

        for i in circles[0,:]:
            cv2.circle(img, (i[0],i[1]),i[2],(b,g,r),2)  #draw the circle
            cv2.circle(img, (i[0],i[1]),2,(b,g,r),3)     #draw the center

调用摄像头
        1.打开摄像头

        capture = cv2.VideoCapture(1)        #0默认为笔记本摄像头

        2.读取摄像头图片

        retval, image = capture.read(1)        # 从摄像头中实时读取视频

调用摄像头整体流程

capture = cv2.VideoCapture(0)  # 打开笔记本内置摄像头
while (capture.isOpened()):  # 笔记本内置摄像头被打开后
    retval, image = capture.read(0)  # 从摄像头中实时读取视频

    cv2.imshow("Video", img)  # 在窗口中显示读取到的视频

    key = cv2.waitKey(1)  # 窗口的图像刷新时间为1毫秒

    if key == 27:  # 如果按下esc
        break
capture.release()  # 关闭笔记本内置摄像头
cv2.destroyAllWindows()  # 销毁显示摄像头视频的窗口

代码整体流程

1.调试每个颜色,获取各个颜色的hsv参数代码
import cv2
import numpy as np

def nothing(*arg):
    pass

#初始化窗口以及进度条
def Trackbar_Init():
    # 1 create windows
    cv2.namedWindow('h_binary')
    cv2.namedWindow('s_binary')
    cv2.namedWindow('v_binary')

# 2 Create Trackbar
    cv2.createTrackbar('hmin', 'h_binary', 6, 179, nothing)
    cv2.createTrackbar('hmax', 'h_binary', 26, 179, nothing)
    cv2.createTrackbar('smin', 's_binary', 110, 255, nothing)
    cv2.createTrackbar('smax', 's_binary', 255, 255, nothing)
    cv2.createTrackbar('vmin', 'v_binary', 140, 255, nothing)
    cv2.createTrackbar('vmax', 'v_binary', 255, 255, nothing)
    #   创建滑动条     滑动条值名称 窗口名称   滑动条值 滑动条阈值 回调函数

# 在HSV色彩空间下得到二值图
def Get_HSV(image):
    
    # 1 get trackbar's value
    hmin = cv2.getTrackbarPos('hmin', 'h_binary')
    hmax = cv2.getTrackbarPos('hmax', 'h_binary')
    smin = cv2.getTrackbarPos('smin', 's_binary')
    smax = cv2.getTrackbarPos('smax', 's_binary')
    vmin = cv2.getTrackbarPos('vmin', 'v_binary')
    vmax = cv2.getTrackbarPos('vmax', 'v_binary')

    # 2 to HSV
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
#    cv2.imshow('hsv', hsv)
    h, s, v = cv2.split(hsv)

    # 3 set threshold (binary image)
    # if value in (min, max):white; otherwise:black
    h_binary = cv2.inRange(np.array(h), np.array(hmin), np.array(hmax))
    s_binary = cv2.inRange(np.array(s), np.array(smin), np.array(smax))
    v_binary = cv2.inRange(np.array(v), np.array(vmin), np.array(vmax))

    # 4 get binary(对H、S、V三个通道分别与操作)
    binary = cv2.bitwise_and(h_binary, cv2.bitwise_and(s_binary, v_binary))

    # 5 Show
    cv2.imshow('h_binary', h_binary)
    cv2.imshow('s_binary', s_binary)
    cv2.imshow('v_binary', v_binary)
    cv2.imshow('binary', binary)

    return binary



Trackbar_Init()
capture = cv2.VideoCapture(1)  # 打开笔记本内置摄像头
while (capture.isOpened()):  # 笔记本内置摄像头被打开后
    retval, image = capture.read(1)  # 从摄像头中实时读取视频
    img = image.copy()

    binary = Get_HSV(image)

    blur = cv2.GaussianBlur(binary,(9,9),0)
    cv2.imshow("blur", blur)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
    Open = cv2.morphologyEx(blur, cv2.MORPH_OPEN, kernel)
    cv2.imshow("Open", Open)
    Close = cv2.morphologyEx(Open, cv2.MORPH_CLOSE, kernel)
    cv2.imshow("close", Close)

    # 6 Hough Circle detect
    circles = cv2.HoughCircles(Close, cv2.HOUGH_GRADIENT, 2, 120, param1=120, param2=100, minRadius=10, maxRadius=300)
    #                                                                     param2:决定圆能否被检测到(越少越容易检测到圆,但相应的也更容易出错)

    if type(circles) != type(None):     #防止没有找到圆形轮廓

        circles = np.uint16(np.around(circles))

        for i in circles[0,:]:
            cv2.circle(img, (i[0],i[1]),i[2],(0,255,255),2)  #draw the circle
            cv2.circle(img, (i[0],i[1]),2,(0,0,255),3)       #画圆心


    cv2.imshow("Video", img)  # 在窗口中显示读取到的视频
    key = cv2.waitKey(1)  # 窗口的图像刷新时间为1毫秒
    if key == 27:  # 如果按下esc
        break
capture.release()  # 关闭笔记本内置摄像头
cv2.destroyAllWindows()  # 销毁显示摄像头视频的窗口

注:这里主要看调整hsv各个参数的最大值和最小值对于最后整体图像的影响,也就是hsv合成后图像的影响,以及各种滤波操作后的影响,在一个通道中效果很好但是放在整体中可能就不一定喽

2.获取每个颜色的参数之后进行整体识别
import cv2
import numpy as np

def nothing(*arg):
    pass


#初始化窗口以及进度条
def Trackbar_Init():
    # 1 create windows
    cv2.namedWindow('h_binary')
    cv2.namedWindow('s_binary')
    cv2.namedWindow('v_binary')

# 2 Create Trackbar
    cv2.createTrackbar('hmin', 'h_binary', 6, 179, nothing)
    cv2.createTrackbar('hmax', 'h_binary', 26, 179, nothing)
    cv2.createTrackbar('smin', 's_binary', 110, 255, nothing)
    cv2.createTrackbar('smax', 's_binary', 255, 255, nothing)
    cv2.createTrackbar('vmin', 'v_binary', 140, 255, nothing)
    cv2.createTrackbar('vmax', 'v_binary', 255, 255, nothing)
    #   创建滑动条     滑动条值名称 窗口名称   滑动条值 滑动条阈值 回调函数


# 在HSV色彩空间下得到二值图
def Get_HSV(image,hmin,hmax,smin,smax,vmin,vmax):
    # 1 get trackbar's value


    # 2 to HSV
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
#    cv2.imshow('hsv', hsv)
    h, s, v = cv2.split(hsv)

    # 3 set threshold (binary image)
    # if value in (min, max):white; otherwise:black
    h_binary = cv2.inRange(np.array(h), np.array(hmin), np.array(hmax))
    s_binary = cv2.inRange(np.array(s), np.array(smin), np.array(smax))
    v_binary = cv2.inRange(np.array(v), np.array(vmin), np.array(vmax))

    # 4 get binary(对H、S、V三个通道分别与操作)
    binary = cv2.bitwise_and(h_binary, cv2.bitwise_and(s_binary, v_binary))

    # 5 Show

#    cv2.imshow('h_binary', h_binary)
#    cv2.imshow('s_binary', s_binary)
#    cv2.imshow('v_binary', v_binary)
#    cv2.imshow('binary', binary)

    return binary


def Image_Processing(binary,color):

    # 3 Gausi blur
    blur = cv2.GaussianBlur(binary, (13, 13), 0)

    # 4 Open
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
    Open = cv2.morphologyEx(blur, cv2.MORPH_OPEN, kernel)

    # 5 Close
    Close = cv2.morphologyEx(Open, cv2.MORPH_CLOSE, kernel)

    cv2.imshow(color, Close)
    # 6 Hough Circle detect
    circles = cv2.HoughCircles(Close, cv2.HOUGH_GRADIENT, 1, 20, param1=200, param2=50, minRadius=1, maxRadius=300)
    #                                                                     param2:决定圆能否被检测到(越少越容易检测到圆,但相应的也更容易出错)
    # judge if circles is exist



    return circles


def draw_circle(img,circles,b,g,r):
    if type(circles) != type(None):     #防止没有找到圆形轮廓
        
        circles = np.uint16(np.around(circles))

        for i in circles[0,:]:
            x, y, r = i[0], i[1], i[2]
            print(x,y,r)

            cv2.circle(img, (i[0],i[1]),i[2],(b,g,r),2)  #draw the circle
            cv2.circle(img, (i[0],i[1]),2,(b,g,r),3)




capture = cv2.VideoCapture(1)  # 打开笔记本内置摄像头
while (capture.isOpened()):  # 笔记本内置摄像头被打开后
    retval, image = capture.read(1)  # 从摄像头中实时读取视频
    #img用做绘图,image用作处理
    img = image.copy()



    #找红球轮廓
    binary_red = Get_HSV(image,0,10,43,255,16,255)

    circle_red = Image_Processing(binary_red,"red")

    draw_circle(img,circle_red,0,0,255)

    #找蓝球轮廓
    binary_blue = Get_HSV(image,90,133,136,255,20,255)

    circle_blue = Image_Processing(binary_blue,"blue")

    draw_circle(img,circle_blue,255,0,0)

    #找黄球轮廓
    binary_yellow = Get_HSV(image,20,27,83,255,155,255)

    circle_yellow = Image_Processing(binary_yellow,"yellow")

    draw_circle(img,circle_yellow,0,255,255)

    #找黑球轮廓
    binary_black = Get_HSV(image,0,73,0,255,0,63)

    circle_black = Image_Processing(binary_black,"black")

    draw_circle(img,circle_black,255,255,255)



    cv2.imshow("Video", img)  # 在窗口中显示读取到的视频
    key = cv2.waitKey(1)  # 窗口的图像刷新时间为1毫秒
    if key == 27:  # 如果按下esc
        break
capture.release()  # 关闭笔记本内置摄像头
cv2.destroyAllWindows()  # 销毁显示摄像头视频的窗口
这里的霍夫圆检测需要多实验,实践出真知

附一张图片,当天弄得时间比较紧张,所以效果不好,多调调参

后期规划:

        1.先用这一版opencv结果和stm32单片机进行联调,当可以达到基础的要求之后,再用其他方法提升检测的精准度

        2.尝试检测兑换区域

        3.在通过yolo增加精确度

### 使用OpenMV开发智能救援小车 #### 组件准备 对于智能救援小车的开发,硬件组件的选择至关重要。Arduino MEGA 2560 和其配套扩展板作为控制核心能够提供足够的I/O接口来连接各种传感器和执行器[^1]。 #### OpenMV相机配置 OpenMV是一款专为机器视觉应用设计的微型计算机视觉平台。它支持多种编程语言,其中Python因其简洁性和强大的库支持成为首选。通过安装官方固件并利用IDE进行脚本编写可以快速实现图像处理功能[^2]。 ```python import sensor, image, time from pyb import UART sensor.reset() # Reset and initialize the sensor. sensor.set_pixformat(sensor.GRAYSCALE) # Set pixel format to RGB565 (or GRAYSCALE) sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240) sensor.skip_frames(time = 2000) # Wait for settings take effect. clock = time.clock() # Create a clock object to track FPS. uart = UART(3, 9600, timeout_char=1000) while(True): img = sensor.snapshot() # Add your code here... ``` #### PID控制器集成 为了使小车能够在复杂环境中稳定行驶,在运动控制系统中引入PID算法是非常必要的。该方法可以根据设定的目标位置调整电机转速从而达到精确导航的目的。 #### 数据传输与通信协议 考虑到实际应用场景可能存在的干扰因素以及数据同步需求,采用UART串口通讯方式可以在一定程度上提高系统的可靠性和实时性。同时也可以考虑加入Wi-Fi模块以便远程监控和调试。 #### 应急避障机制 针对可能出现的障碍物碰撞风险,可在车身四周布置超声波测距仪或其他类型的接近开关,并将其检测结果反馈给主控单元用于触发紧急制动程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值