DSP

霍夫圆变换

2019-07-13 12:28发布

对于直线来说,一条直线能有参数极径级角表示,而对圆来说我们需要三个参数来表示一个圆 1420671-7dd1d64abd923a5a.png 1420671-f4422033508c9fb4.png 在OpenCV中,我们常常通过一个叫“霍夫梯度法”的方法来解决圆变换的问题。霍夫梯度法的原理
(1)首先对图像应用边缘检测,比如canny边缘检测(2)然后对边缘图像中的每一个非零点,考虑其局部梯度,即用sobel函数计算x和y方向的Sobel一阶导数得到的梯度。(3)可用得到的梯度,有斜率指定的直线上的每个点都在累加器中累加,这里的斜率是从一个指定的最小值到指定的最大值得距离(4)同时标记图像中每一个非0像素的位置(5)然后从二维累加器中这些点钟选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻,这些候选的中心按照累加值将序排列,以便于最支持像素的中心首先出现(6)接下来对每一个中心,考虑所有的非0元素(7)这些元素按照其与中心的距离排序。从最大半径到最小半径算起,选择非0像素最支持的一条半径(8)如果一个中心收到边缘图像非0像素的最充分支持,并且到前期被选择的中心有足够的距离,那么他就会被保留下来。这个实现可以使算法执行起来更高效,获取更加重要的是能够帮助解决三维累加器中国会产生许多噪声并且使得结构不稳定的稀疏分布问题。霍夫梯度法的缺点(1)在霍夫梯度法中,我们使用Sobel导数来计算局部梯度,那么随之而来的假设是,它可以视作等同于一条局部切线,这并不是一个稳定的做法,在大多数的情况下,这样做会得到正确答案,但或许会输出产生一些噪声。(2)在边缘图像中的整个非0像素集,被看做每个中心的候选部分。因此如果把累加器的阈值设置的偏低,算法需要消耗更长的时间。因此,每一个中心只会选择一个圆,如果有同心圆,就只能选择一个(3)因为中心是按照其关联的累加器值得升序排列的,并且如果新的中心过于接近之前已经接受的中心的话,就不被保留下来,并且当有很多的同心圆或者是近似同心圆时,霍夫梯度法的倾向是保留最大的一个圆,可以说这也是一种比较极端的算法,因为子在这里默认Sobel导数会产生噪声,若是对于无穷分辨率的平滑图像而言,这是必须的。霍夫圆变换函数:HounghCircles()函数
void HoughCircles(InputArray image,                               OutputArray circles,
                              int method,                               double dp,                               double minDist,                               double param1 =100,                              double param2 =100,                              int minRadius =0,                             int maxRadius =0);
函数参数详解 1420671-df262e7af61f5c9d.png 1420671-5e82c9789a59f818.png

代码实现

NSString*image =@"dkdk.jpg";
UIImage*image1 = [UIImageimageNamed:image]; Matim; UIImageToMat(image1, im); if(im.empty()) { return; } //创建零时变量 Mat midImage,dstImage; //转换为灰度图像进行图像平滑 cvtColor(im, midImage,COLOR_BGR2GRAY); GaussianBlur(midImage, midImage,cv::Size(9,9),2,2); //进行霍夫圆变换 std::vector circle;
HoughCircles(midImage, circle,HOUGH_GRADIENT,1.5,10); //依次在图中绘制出圆 for(size_ti =0; i < circle.size(); i++) { //圆心 cv::Point center(cvRound(circle[i][0]),cvRound(circle[i][1])); //半径 int radius =cvRound(circle[i][2]); //绘制 cv::circle(midImage, center, radius,Scalar(0,88,255)); } self.secondImageView.image=MatToUIImage(midImage);

效果

1420671-87b1e3f60d486f87.png

热门文章