最近在学习OpenCV,OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,拥有丰富的图像处理和计算机视觉方面的算法,同时提供了很多通用算法API。最新的opencv2的版本为2.4.13。下载地址http://opencv.org/
更简单的python版本:识别圆形(python版)
今天做的就是在视频(图片)中识别一个圆形。先上效果图:
可以看到识别了视频中的乒乓球,其实opencv里直接就有识别圆形的API,运用霍夫变换算法检测出图中的圆。
1.原理
对直线来说, 一条直线能由参数极径极角 (γ, θ) 表示. 而对圆来说, 我们需要三个参数来表示一个圆。现在原图像的边缘图像的任意点对应的经过这个点的所有可能圆是在三维空间有下面这三个参数来表示了,其对应一条三维空间的曲线. 那么与二维的霍夫线变换同样的道理,对于多个边缘点越多这些点对应的三维空间曲线交于一点那么他们经过的共同圆上的点就越多,类似的我们也就可以用同样的阈值的方法来判断一个圆是否被检测到, 这就是标准霍夫圆变换的原理, 但也正是在三维空间的计算量大大增加的原因, 标准霍夫圆变化很难被应用到实际中:
C: ( X , Y , γ )
2.方法
void HoughCircles( InputArray image, OutputArray circles,int method, double dp, double minDist,double param1=100, double param2=100,int minRadius=0, int maxRadius=0 );
image为输入图像,要求是灰度图像
circles为输出圆向量,每个向量包括三个浮点型的元素——(x,y,radius)
method为使用霍夫变换圆检测的算法,它的参数是CV_HOUGH_GRADIENT
dp为第一阶段所使用的霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半
minDist为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心
param1有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
param2也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
minRadius和maxRadius为所检测到的圆半径的最小值和最大值
3.代码
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{
//开起摄像头
VideoCapture capture;
capture.open(1);
Mat edges; //定义转化的灰度图
if (!capture.isOpened())
return -1;
namedWindow("【效果图】", CV_WINDOW_NORMAL);
while (1)
{
Mat frame;
capture >> frame;
if (!frame.data)
return -1;
cvtColor(frame, edges, CV_BGR2GRAY);
//高斯滤波
GaussianBlur(edges, edges, Size(7, 7), 2, 2);
vector<Vec3f> circles;
//霍夫圆
HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
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(frame, center, 3, Scalar(0, 255, 0), -1, 8, 0);
//绘制圆轮廓
circle(frame, center, radius, Scalar(155, 50, 255), 3, 8, 0);
}
imshow("【效果图】", frame);
waitKey(30);
}
return 0;
}
4.说明
VideoCapture capture;
capture.open(1);
开启摄像头,本机自带摄像头传0,usb摄像头传1
cvtColor(frame, edges, CV_BGR2GRAY);
转成灰度图
GaussianBlur(edges, edges, Size(7, 7), 2, 2);
高斯模糊降低噪声
vector<Vec3f> circles;
//霍夫圆
HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
霍夫圆变换
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(frame, center, 3, Scalar(0, 255, 0), -1, 8, 0);
//绘制圆轮廓
circle(frame, center, radius, Scalar(155, 50, 255), 3, 8, 0);
}
绘制检测到的圆