Robomaster装甲板识别-基于python+opencv的思路分享
Robomaster视觉-装甲板识别
环境:windows10、pycharm2017、、python3.64、opencv3
***先上个效果图吧,图中是加了一些其他算法的,不是单独的识别,还有一些卡尔曼滤波,svm等。我们先出基本的识别思路开始。
第一步-导入需要的库进行图像预处理
- 读取摄像头的信息后,对图片进行hsv色彩空间的转换,对于红蓝而言也可以采用颜色通道相减的方法获取蓝色、红色(两种方法各有优点)
- 进行图像形态学操作,包括开闭操作,腐蚀膨胀等等
- 得到一个较为清晰的二值图,其中镜头中红、蓝色为高亮区。
***分享一下我自己代码,其中形态学操作,hsv色彩空间转换都进行了模块化,可以直接使用。
这是第一部分的一个主程序由它调用其他下面的程序:
def read_morphology(cap): # read cap and morphological operation to get led binary image.ret, frame = cap.read()# frame = cv.flip(frame, 1)# frame = cv.flip(frame, 1)open = cv.getTrackbarPos('open', 'mor_adjust')close = cv.getTrackbarPos('close', 'mor_adjust')erode = cv.getTrackbarPos('erode', 'mor_adjust')dilate = cv.getTrackbarPos('dilate', 'mor_adjust')frame = cv.resize(frame, (WIDTH, HIGH), interpolation=cv.INTER_CUBIC)mask = hsv_change(frame)# dst_open = open_binary(mask, open, open)dst_close = close_binary(mask, close, close)dst_erode = erode_binary(dst_close, erode, erode)dst_dilate = dilate_binary(dst_erode, dilate, dilate)cv.circle(frame, (int(WIDTH / 2), int(HIGH / 2)), 2, (255, 0, 255), -1)cv.imshow("erode", mask)return dst_dilate, frame
hsv色彩空间转换,为了调参数方便我设置了滑块,方便调参调整hsv的阈值来获得一个较好的阈值效果,但是这种根据阈值来调整的会受光线影响比较严重 ,rm的场地比较黑暗,但是能也会有些影响,可以加一些滤光片或者增加摄像头的曝光等等来进行调整。
def nothing(x):passdef creatTrackbar(): # creat trackbar to adjust the color threshold.# blue# cv.createTrackbar("hmin", "color_adjust", 0, 255, nothing)# cv.createTrackbar("hmax", "color_adjust", 250, 255, nothing)# cv.createTrackbar("smin", "color_adjust", 0, 255, nothing)# cv.createTrackbar("smax", "color_adjust", 143, 255, nothing)# cv.createTrackbar("vmin", "color_adjust", 255, 255, nothing)# cv.createTrackbar("vmax", "color_adjust", 255, 255, nothing)# redcv.createTrackbar("hmin", "color_adjust", 0, 255, nothing)cv.createTrackbar("hmax", "color_adjust", 255, 255, nothing)cv.createTrackbar("smin", "color_adjust", 3, 255, nothing)cv.createTrackbar("smax", "color_adjust", 255, 255, nothing)cv.createTrackbar("vmin", "color_adjust", 245, 255, nothing)cv.createTrackbar("vmax", "color_adjust", 255, 255, nothing)cv.createTrackbar("open", "mor_adjust", 1, 30, nothing)cv.createTrackbar("close", "mor_adjust", 5, 30, nothing)cv.createTrackbar("erode", "mor_adjust", 2, 30, nothing)cv.createTrackbar("dilate", "mor_adjust", 5, 30, nothing)def hsv_change(frame): # hsv channel separation.hmin = cv.getTrackbarPos('hmin', 'color_adjust')hmax = cv.getTrackbarPos('hmax', 'color_adjust')smin = cv.getTrackbarPos('smin', 'color_adjust')smax = cv.getTrackbarPos('smax', 'color_adjust')vmin = cv.getTrackbarPos('vmin', 'color_adjust')vmax = cv.getTrackbarPos('vmax', 'color_adjust')# gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)# cv.imshow("gray", gray)hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)lower_hsv = np.array([hmin, smin, vmin])upper_hsv = np.array([hmax, smax, vmax])mask = cv.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv)return mask
形态学操作,模块化可直接调用使用
def open_binary(binary, x, y):kernel = cv.getStructuringElement(cv.MORPH_RECT, (x, y))dst = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)return dstdef close_binary(binary, x, y):kernel = cv.getStructuringElement(cv.MORPH_RECT, (x, y))dst = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel)return dstdef erode_binary(binary, x, y):kernel = cv.getStructuringElement(cv.MORPH_RECT, (x, y))dst = cv.erode(binary, kernel)return dstdef dilate_binary(binary, x, y):kernel = cv.getStructuringElement(cv.MORPH_RECT, (x, y))dst = cv.dilate(binary, kernel)return dst
第二部分 -筛选寻找装甲板
- 由第一步得到的图像找出画面中所以的红、蓝区域,用读取区域最小外接矩形获取对应的面积,高、宽、旋转角、中心点等等信息。
- 遍历每一个矩形,将获取的可能为装甲板的区域的信息存储在python-字典中,并对不同的信息不同的键值加以区分。
- 筛选这些信息,留下可能是装甲板的信息,删去非装甲板的信息。例如,遍历对比每一对的信息的高宽比是否满足某个条件、两个矩形块之间的中心点距离是否满足一定大小。这里需要说明,是把所有的红、蓝色区域都作为一个单独的矩形区域进行判断,所有需要判断的是两两之间的关系,而不是单独一个矩形块的关系。当然也可以加入一些单独的判断,例如装甲板的灯条是个长方形的,它自己一个灯条的高宽比肯定满足某个范围,如果单独一个矩形区域都不满足灯条基本的高宽比,那这个必然不是装甲板的一个灯条。
- 通过层层筛选可以最终得到一个字典,里面包含了画面中所以可能是装甲板的信息,然后通过画图将他们画出来,再调试找到准确率最高的情况。这里需要说明,在筛选之前最好对信息进行一个排序,这样不容易造成一个装甲板的一个灯条和另一个装甲板的另一个灯条被识别成一个装甲板的情况。同时记得结束后将字典清空后再进行下一次筛选,否则可能会报错。
***下面附上这部分代码
def find_contours(binary, frame): # find contours and main screening section_, contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)length = len(contours)data_list = []first_data = []second_data1 = []second_data2 = []c = 0d = 0if length > 0:# print("---founding---")for i, contour in enumerate(contours):data_dict = dict()# print("countour", contour)area = cv.contourArea(contour)rect = cv.minAreaRect(contour)rx, ry = rect[0]rw = rect[1][0]rh = rect[1][1]z = rect[2]coor = cv.boxPoints(rect)x1 = coor[0][0]y1 = coor[0][1]x2 = coor[1][0]y2 = coor[1][1]x3 = coor[2][0]y3 = coor[2][1]x4 = coor[3][0]y4 = coor[3][1]# if i >= 1:data_dict["area"] = areadata_dict["rx"] = rxdata_dict["ry"] = rydata_dict["rh"] = rhdata_dict["rw"] = rwdata_dict["z"] = zdata_dict["x1"] = x1data_dict["y1"] = y1data_dict["x2"] = x2data_dict["y2"] = y2data_dict["x3"] = x3data_dict["y3"] = y3data_dict["x4"] = x4data_dict["y4"] = y4data_list.append(data_dict)for i in range(len(data_list)):data_rh = data_list[i].get("rh", 0)data_rw = data_list[i].get("rw", 0)data_area = data_list[i].get("area", 0)if (float(data_rh / data_rw) >= 0.2) \and (float(data_rh / data_rw) <= 4) \and data_area >= 20:first_data.append(data_list[i])else:passfor i in range(len(first_data)):c = i + 1while c < len(first_data):data_ryi = float(first_data[i].get("ry", 0))data_ryc = float(first_data[c].get("ry", 0))data_rhi = float(first_data[i].get("rh", 0))data_rhc = float(first_data[c].get("rh", 0))data_rxi = float(first_data[i].get("rx", 0))data_rxc = float(first_data[c].get("rx", 0))if (abs(data_ryi - data_ryc) <= 3 * ((data_rhi + data_rhc) / 2)) \and (abs(data_rhi - data_rhc) <= 0.2 * max(data_rhi, data_rhc)) \and (abs(data_rxi - data_rxc) <= (6 / 2) * ((data_rhi + data_rhc) / 2)):second_data1.append(first_data[i])second_data2.append(first_data[c])c = c + 1# for i in range(len(second_data1)):# data_z1 = second_data1[i].get("z", 0)# data_z2 = second_data2[i].get("z", 0)# if abs(data_z1 - data_z2) <= 6:# third_data1.append(second_data1[i])# third_data2.append(second_data2[i])if len(second_data1):global dataList_cdataList_c.clear()for i in range(len(second_data1)):rectangle_x1 = int(second_data1[i]["x1"])rectangle_y1 = int(second_data1[i]["y1"])rectangle_x2 = int(second_data2[i]["x3"])rectangle_y2 = int(second_data2[i]["y3"])if abs(rectangle_y1 - rectangle_y2) <= (6 / 2) * (abs(rectangle_x1 - rectangle_x2)):global point1_1x, point1_1y, point1_2x, point1_2y, point1_3x, point1_3y, point1_4x, point1_4yglobal point2_1x, point2_1y, point2_2x, point2_2y, point2_3x, point2_3y, point2_4x, point2_4ypoint1_1x = second_data1[i]["x1"]point1_1y = second_data1[i]["y1"]point1_2x = second_data1[i]["x2"]point1_2y = second_data1[i]["y2"]point1_3x = second_data1[i]["x3"]point1_3y = second_data1[i]["y3"]point1_4x = second_data1[i]["x4"]point1_4y = second_data1[i]["y4"]point2_1x = second_data2[i]["x1"]point2_1y = second_data1[i]["y1"]point2_2x = second_data1[i]["x2"]point2_2y = second_data1[i]["y2"]point2_3x = second_data1[i]["x3"]point2_3y = second_data1[i]["y3"]point2_4x = second_data1[i]["x4"]point2_4y = second_data1[i]["y4"]if point1_1x > point2_1x:passcv.rectangle(frame, (point2_2x, point2_2y), (point1_4x, point1_4y), (255, 255, 0), 2)else:point1_1x, point2_1x = point2_1x, point1_1xpoint1_2x, point2_2x = point2_2x, point1_2xpoint1_3x, point2_3x = point2_3x, point1_3xpoint1_4x, point2_4x = point2_4x, point1_4xpoint1_1y, point2_1y = point2_1y, point1_1ypoint1_2y, point2_2y = point2_2y, point1_2ypoint1_3y, point2_3y = point2_3y, point1_3ypoint1_4y, point2_4y = point2_4y, point1_4ycv.rectangle(frame, (point2_1x, point2_1y), (point1_3x, point1_3y), (255, 255, 0), 2)cv.putText(frame, "target1:", (rectangle_x2, rectangle_y2 - 5), cv.FONT_HERSHEY_SIMPLEX,0.5, [255, 255, 255])center = (int((point2_2x + point1_4x) / 2), int((point2_2y + point1_4y) / 2))cv.circle(frame, center, 2, (0, 0, 255), -1) # 画出重心dataList_c.append(center)high = (rectangle_y1, rectangle_y2)dataRange.append(high)else:print("---not find---")dataList_c.clear()data_list.clear()
- 到这一步基本的识别就结束了,之后就该进行一些算法的优化以及提高识别速度等等,这里可以采用神经网络训练识别数字,svm也可,卡尔曼滤波添加提前量增加击打准确,增加线进程提高速度等等。
总结
1,图片数据读取:在While语句中从摄像头中读入数据,以帧一帧的形式加以进入后续处理。
2,预处理:对读入进来的图片预处理,包括,转化到HSV色彩空间、根据不同阈值不断调整提取出鲜明的红色/蓝色、对提取出来的包含各种噪声的二值图进行腐蚀膨胀处理,得到完整的可能含有多个的明显的灯条信息并且噪声较小或没有噪声后。即算预处理结束。
3,筛选灯条:对预处理完的灯条进行轮廓查找进入find_contours()函数,遍历cv2.findContours()opencvAPI查找出的轮廓,根据灯条高宽比、面积大小、两列灯条之间的宽度差、高度差把是灯条对的轮廓筛选出来,其中以待筛选的一对灯条的高度平均值或max(待筛选的一对灯条)作为比对标准进行筛选。画出所有灯条对,并确定中心及击打点。
4,测距及数据处理:根据PNP算法、cv2.solvePnP()API等单目测距出目标点距离摄像头的距离,并根据姿势计算获得欧拉角作为电控云台转动的数据。
5,主要框架流程:将各个函数步骤逐步封装,并在主函数的While读图语句中分步调用,并作为主线程,将筛选灯条svm算法、测距及数据处理和串口发送,作为两个分线程,各自运行互不影响提高识别速度。(也可以开多个线程,根据自己算法而定)
Robomaster装甲板识别-基于python+opencv的思路分享相关推荐
- 基于python+OpenCV的车牌号码识别
基于python+OpenCV的车牌号码识别 车牌识别行业已具备一定的市场规模,在电子警察.公路卡口.停车场.商业管理.汽修服务等领域已取得了部分应用.一个典型的车辆牌照识别系统一般包括以下4个部分: ...
- RoboMaster视觉教程(4)装甲板识别算法
RoboMaster视觉教程(4)装甲板识别算法 概览 下面是一些资料链接,篇篇经典! 装甲板识别 test_sentry.cpp 分析一下装甲板 识别函数 int ArmorDetector::de ...
- 基于yolov5的目标检测和模型训练(Miniconda3+PyTorch+Pycharm+实战项目——装甲板识别)
目录 一.环境配置和源码获取 1.Miniconda 2.MIniconda虚拟环境配置PyTorch 3.yolov5项目源码 4.pycharm 二.目标检测 三.模型训练 1.数据集 1.ima ...
- 基于python opencv人脸识别的签到系统
基于python opencv人脸识别的签到系统 前言 先看下效果 实现的功能 开始准备 页面的构建 功能实现 代码部分 总结 前言 一个基于opencv人脸识别和TensorFlow进行模型训练的人 ...
- 【开源分享】基于Python+OpenCV+PyQt5车牌识别(GUI界面)
亲测无错:基于Python+OpenCV+PyQt5车牌识别(GUI界面)绝对可以用的!!!!! 基于Python+OpenCV+PyQt5车牌识别(GUI界面) 参考文档
- 东南大学RM装甲板识别算法详解
rm中,装甲板的识别在比赛中可谓是最基础的算法.而在各个开源框架中,该算法也可以说最为成熟.出于学习目的,之后将对比多个高校或网络代码(),尝试学习各个rm装甲板识别算法的优点和流程. 这次先是东南大 ...
- 视觉组考核——装甲板识别
视觉组考核--装甲板识别 识别Robomaster的装甲板的简易程序 算法分析 装甲板识别主要分这几步 图像处理->提取灯柱同时对灯柱进行筛选->灯条匹配->装甲板的筛选 1.图像处 ...
- 基于Python+OpenCV车道线检测(直道和弯道)
基于Python+OpenCV车道线检测(直道和弯道) 基于Python+OpenCV车道线检测(直道和弯道)
- RoboMasterAI挑战赛-装甲板识别与测距 jetsonNX+realsense
RoboMasterAI挑战赛-装甲板识别与测距 jetsonNX+realsense 1.演示视频 2.识别测距代码 2.1 主要思路 2.2 主要代码 1.演示视频 识别测距:https://ww ...
最新文章
- GraphQL是什么“渣渣“?它想干掉RESTful
- Smalidea+IntelliJ IDEA/Android Studio无源码调试
- 设计模式初探之设计模式六大原则(4):接口隔离原则
- Apache Ignite变得简单:第一个Java应用程序
- iOS开发用如何用类quot;SKStoreProductViewControllerquot;跳转AppStore点赞评分?
- mysql查询临时表是否存在_[转]SQL判断临时表是否存在
- 基于Redis的微博计算好友关系
- php 采集网站关键字,php远程获取网站的关键字信息(并附:php判断字符串编码)...
- Java使用ODBC连接Access数据库
- 论文的中期检查表应该怎么写?
- pycharm占用c盘
- puts和printf的区别
- MySQL_11_范式优化
- Go Cloud项目开源发布:Go语言将成为云端应用开发的首选语言?
- 基于Visual Studio 2003/2005的Office插件开发FAQ
- MAC远程桌面控制Ubuntu
- Python自动化小技巧11——excel文件的文字内容筛选
- pre 图像稳定_什么是图像稳定,它如何工作?
- 面经 | 我是如何通过校招拿到京东的Offer的。
- Depix:还原马赛克工具的试用及总结
热门文章
- PS系列之 -- 利用蒙版取消图片衔接的痕迹
- Android Studio SQLite数据库应用(一)
- 评论有礼丨你关心的都安排上了!Cocos开发者沙龙「深圳站」下周回归,点击报名...
- java 蓝桥杯 李白打酒
- 昵称脱敏只显示第一个字剩下的显示星号
- tbody超长显示滚动条
- (微信开发)PHP curl模拟登陆教务系统查询成绩查询课表实现微信查成绩差课表功能
- 全国青少年信息素养大赛图形化编程初赛·模拟四卷,含答案解析
- xftp 下载文件时提示 you do not have permission to download this folder
- 文字转语音,可在linux系统部署