在开源龙芯1c开发板上用opencv检测图片中网球并输出圆心坐标和半径

news/2024/10/25 16:24:14/

原意是想做一个捡网球的机器人,识别网球就是必须的。项目地址http://git.oschina.net/caogos/OpenLoongsonPickUpTennisRobot

参考了 http://www.pyimagesearch.com/2015/09/14/ball-tracking-with-opencv/

主要思路

用cvtColor()将图像转换到HSV颜色空间,用inRange()根据网球颜色提取出网球,通过形态学变换(膨胀和腐蚀)除去网球上的条纹和字,使识别出的网球更圆,用findContours()找轮廓,再用minEnclosingCircle()找轮廓的最小外接圆。

源码

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include "v4l2_capture_picture.h"using namespace std;
using namespace cv;#define CAPTURE_PICTURE_PATH 		"/test/PickUpTennisRobot/capture_picture.jpg"// 图片中网球的最小半径,注意不是实际的网球半径
#define MIN_CIRCLE_RADIUS			(25)// 打印当前时间
void PrintCurrentTime(void)
{struct timeval tv;gettimeofday(&tv, NULL);cout << tv.tv_sec << "." << tv.tv_usec << endl;
}int main(int argc, char** argv)
{Mat src, src_gray;int ret = 0;/*// 通过摄像头抓拍ret = capture_picture(CAPTURE_PICTURE_PATH);if (0 != ret){std::cout << "capture_picture fail." << std::endl;return ret;}
*//// Read the imagesrc = imread(CAPTURE_PICTURE_PATH);if( !src.data ){cout << "imread src picture fail." << endl;return -1; }PrintCurrentTime();// 转换为hsv颜色空间Mat hsv;cvtColor(src, hsv, CV_BGR2HSV);// 通过颜色找网球// 这里是识别的关键,请仔细研究百度百科的"HSV颜色空间"// 理论上:H的取值范围是0-360,S是0%-100%即0-1,V是0%-100%即0-1// 实际上opencv在实现上做了调整:H的取值范围为0-180,S为0-255,V为0-255// 比如理论上绿色的H值为120,在opencv里绿色为60,即理论值的一半// 调试方法为把S和V的范围选为0-255,根据实物的颜色确定H值,// H值确定得好基本上可以过滤出想要的效果,然后通过S和V来优化// 比如网球可以先把范围选为Scalar(45,0,0)到Scalar(75,255,255),运行结果显示白色区域太多,未能过滤出网球// 继续缩小H值为Scalar(50,0,0)到Scalar(70,255,255),运行结果中可以看到网球了,但是还不理想// 继续缩小,调整范围为Scalar(30,0,0)到Scalar(60,255,255),这时inRange已经能准确过滤出网球了// 最后通过S和V的值来微调,比如过滤掉网球的影子等Mat mask;inRange(hsv, Scalar(45,5, 200), Scalar(60,255,255), mask);imwrite("inRange.jpg", mask);// 通过膨胀、腐蚀,去除网球上的字和条纹int structElemSize = 10;Mat dilate_dst, erode_dst;Mat element = getStructuringElement(MORPH_CROSS, Size(2*structElemSize+1, 2*structElemSize+1));dilate(mask, dilate_dst, element);
//	imwrite("dilate_dst.jpg", dilate_dst);erode(dilate_dst, erode_dst, element);imwrite("erode_dst.jpg", erode_dst);// 获取轮廓,圆vector<vector<Point> > contours;findContours(erode_dst, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);cout << "contours size=" << contours.size() << endl;
/*// 画出轮廓Mat matContours(src.size(), CV_8U, Scalar(255));// 参数为:画板,轮廓,轮廓指示(这里画出所有轮廓),颜色,线粗drawContours(matContours, contours, -1, Scalar(0), 2);imwrite("matContours.bmp", matContours);Mat srcContours = imread(CAPTURE_PICTURE_PATH);drawContours(srcContours, contours, -1, Scalar(0,0,255), 2);imwrite("matContours_src.bmp", srcContours);
*/// 最小外接圆Mat matMinEnclosingCircle = imread(CAPTURE_PICTURE_PATH);float radius;Point2f center;for (size_t i=0; i<contours.size(); i++){// 计算轮廓的最小外接圆minEnclosingCircle(Mat(contours[i]), center, radius);// 过滤掉半径太小的外接圆(半径太小的不是网球)if (MIN_CIRCLE_RADIUS > radius){continue;}// 画出最小外接圆circle(matMinEnclosingCircle, center, static_cast<int>(radius), Scalar(0,0,255), 2);cout << i+1 << " cirecle:" << " x=" << center.x << ", y=" << center.y << ", radius=" << radius << endl;}imwrite("minEnclosingCircle.bmp", matMinEnclosingCircle);PrintCurrentTime();return 0;
}


Makefile

all:mipsel-linux-gcc -Wall -c v4l2_capture_picture.c -o v4l2_capture_picture.omipsel-linux-gcc -Wall -c main.cpp -o main.o -I/home/develop/opencv/opencv-2.4.9-ls1x-lib/includemipsel-linux-g++  *.o -o PickUpTennisRobot -L/home/develop/opencv/opencv-2.4.9-ls1x-lib/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lpthread -lrtcp PickUpTennisRobot /nfsramdisk/LS1xrootfs-demo/test/PickUpTennisRobotclean:rm *.o PickUpTennisRobot


重难点

对HSV的理解和正确使用函数inRange()是关键。上面源码中已经写了很多注释了,多看几遍百度百科里的“HSV颜色空间”,同时要正确理解函数inRange()每个参数的意思。
形态学变换(腐蚀和膨胀)有利于提高识别的准确性,这里耗时最多。

识别的准确性,可以通过最小外接圆与网球的贴合程度,越靠近,则精度越高。

实际应用中需要在精度和速度上平衡。
同一张图片笔记本屏幕看到的和台式机的液晶显示器看到的有差别,另外,我在pc上用qt做的和龙芯1c开发板上对HSV中的V(明暗程度)有些不一样,理论上pc上和开发板上运行结果应该一样的,这个还不知道原因。

运行效果

开发板上

原图


inRange()得到的


膨胀


腐蚀


轮廓


最小外接圆(背景为原图)









http://www.ppmy.cn/news/319176.html

相关文章

【NDN IoT】Challenges in IoT Networking via TCP/IP Architecture 全文翻译

Challenges in IoT Networking via TCP/IP Architecture 在TCP/IP体系结构下物联网络存在的挑战 Wentao Shang Yingdi Yu UCLA UCLA Los Angeles, CA Los Angeles, CA wentaocs.ucla.edu yingdics.…

Windows系统电脑常用快捷键

文章目录 ReadMe1、最常用的筛选2、Ctrl键功能3、Alt功能4、Shift快捷键5、WORD全套快捷键小技巧6、WIN7、最上面FN快捷键如有错误或者需要补充的欢迎评论区留言指正&#xff01; ReadMe 本文内容比较多&#xff0c;可以使用CtrlF 精准查找定位。 1、最常用的筛选 winE 打开…

内存取证-Volatility安装使用以及一些CTF比赛题目

一 、简介 Volatility是一款开源内存取证框架&#xff0c;能够对导出的内存镜像进行分析&#xff0c;通过获取内核数据结构&#xff0c;使用插件获取内存的详细情况以及系统的运行状态。 本文涉及附件下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1r0t5k4gFmi…

内存取证-volatility工具的使用 (史上更全教程,更全命令)

目录 内存取证-volatility工具的使用 一&#xff0c;简介 二&#xff0c;安装Volatility 1.windows下 2. Linux下&#xff08;这里kali为例&#xff09; 三 、安装插件 四&#xff0c;工具介绍help 五&#xff0c;命令格式 六&#xff0c;常用命令插件 ❤可以先查看…

软件工程——计算机

【原题】&#xff1a;以下表述错误的是&#xff08;  &#xff09;。 单项选择题 A、高级语言的命令用英文单词来表示 B、高级语言的语法很接近人类语言 C、高级语言的执行速度比低级语言快 D、同一高级语言可在不同形式的计算机上执行 【解析】&#xff1a;…

数字视频编解码基础知识大全

原文转载自&#xff1a;http://blog.csdn.net/gougouzhuzhu/article/details/1828535 图像及视频基础知识 一、光和颜色 1 光和颜色 可见光是波长在380 nm&#xff5e;780 nm 之间的电磁波&#xff0c;我们看到的大多数光不是 一种波长的光&#xff0c;而是由许多不同波长…

Altium Designer -- 精心总结

如需转载请注明出处&#xff1a;http://blog.csdn.net/qq_29350001/article/details/52199356 以前是使用DXP2004来画图的&#xff0c;后来转行。想来已经有一年半的时间没有画过了。突然转到AD&#xff0c;有些不适应。用了下发觉很多功能确实比DXP要来的强大。花了不少时间和…

基础回顾:10W+ 字 C 语言入门教程(上)

目录 计算机常识什么是计算机程序?什么是计算机语言 ?常见的计算机语言类型有哪些?什么是C语言?C语言历史C语言标准C语言现状为什么要学习C语言?如何学好C语言工欲善其事必先利其器编写C语言程序用什么工具 ?什么是Qt Creator ?Qt Creator安装什么是环境变量?为什么要配…