您的位置:首页 > 其它

基于颜色和圆对乒乓球识别

2017-01-13 08:52 302 查看
实际例程源于本人的挑战杯作品——基于视觉的捡球机器人。
配置环境:vs2015+opencv3.0+win10/ubuntu14.04
机器人通过自带的摄像头对散落在地上的乒乓球进行识别,随后进行拾取。本作品的主要难度在于如何在复杂的背景中准确地识别到乒乓球并跟踪。以及在识别到乒乓球后如何使机器人准确的向乒乓球运行。
此次的程序为最初版。先用颜色识别对整个图像进行过滤,然后再对过滤后的图像进行霍夫找圆。
缺点:程序运行速度慢,光线的影响比较大,找到的圆不够稳定。

例程(win10)
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int g_nThresh = 100;//137
Mat canny_output;
Mat imgOriginal;
Mat imgHSV;
Mat imgThresholded;//二值化后的图像数组
Mat bf;//对灰度图像进行双边滤波
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat dstImage;
//对过滤颜色的范围的确定
int iLowH = 9;
int iHighH = 31;
int iLowS = 135;
int iHighS = 255;
int iLowV = 231;
int iHighV = 255;

int main(int argc, char** argv)
{
VideoCapture cap(0); //capture the video from web cam

if (!cap.isOpened())  // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}

while (true)
{

bool bSuccess = cap.read(imgOriginal); // read a new frame from video

if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
//区分颜色*****************************************************************************************************
vector<Mat> hsvSplit;//cevtor 容器
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

//因为我们读取的是彩色图,直方图均衡化需要在HSV空间做
split(imgHSV, hsvSplit);//(多通道数组-》容器)
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, imgHSV);

inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image

//开操作 (去除一些噪点)
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);

//闭操作 (连接一些连通域)
//morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);

//addWeighted(imgThresholded, 1, canny_output, 1, 0., dstImage);
//morphologyEx(dstImage, dstImage, MORPH_CLOSE, element);

//找圆************************************************************************************************************

blur(imgThresholded, bf, Size(3, 3));
//用Canny算子检测边缘
Canny(bf, canny_output, g_nThresh, g_nThresh * 2, 3);
//开操作 (去除一些噪点)
morphologyEx(canny_output, canny_output, MORPH_OPEN, element);

//闭操作 (连接一些连通域)
morphologyEx(canny_output, canny_output, MORPH_CLOSE, element);

vector<Vec3f> circles;//声明一个向量,保存检测出的圆的圆心坐标和半径
HoughCircles(canny_output, circles, CV_HOUGH_GRADIENT, 1, 70, 250, 10, 1, 100);//霍夫变换检测圆1.5, 5, 150, 80, 1, 50

cout << "x=\ty=\tr=" << endl;
for (size_t i = 0; i < circles.size(); i++)//把霍夫变换检测出的圆画出来
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);

circle(imgOriginal, center, radius, Scalar(255, 255, 255), 5, 8, 0);

cout << cvRound(circles[i][0]) << "\t" << cvRound(circles[i][1]) << "\t"
<< cvRound(circles[i][2]) << endl;//在控制台输出圆心坐标和半径
}
//~~~~~~~~~~~~~~~~~~~~~~~~
imshow("imgThresholded", imgThresholded);//滤过颜色
imshow("imgOriginal", imgOriginal);//寻找边沿
imshow("canny_output", canny_output);//原图显示找出的圆

char key = (char)waitKey(20);
if (key == 27)
break;
}

return 0;

}


运行图片
 



            对一个乒乓球的识别
 



                    
                                                                         外加一个干扰球
 



                                                                            多个球的识别

如图可见,几次识别虽然都准确,但是图像在处理的过程中受光线的影响很大。这仍是以后优化的重点。
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: