Java+opencv4.1.0 实现圆型检测功能

1. opencv函数原型

HoughCircles:霍夫变换圆形检测

/**
* @param image:输入图像:8-bit,灰度图
* @param circles:输出圆的结果。
* @param method:定义检测图像中圆的方法。目前唯一实现的方法是HOUGH_GRADIENT。
* @param dp:寻找圆弧圆心的累计分辨率,这个参数允许创建一个比输入图像分辨率低的累加器。
*          (这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。
*          如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨
*          率受此影响会变小(此情况下为一半)。dp的值不能比1小。
* @param minDist:该参数是让算法能明显区分的两个不同圆之间的最小距离。
* @param param1:用于Canny的边缘阀值上限,下限被置为上限的一半。
* @param param2:HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圈子越多。
* @param minRadius:最小圆半径。
* @param maxRadius:最大圆半径。
*/
Imgproc.HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius)

circle:circle()函数

/**
* @param img:源图像
* @param center:圆的圆心坐标
* @param radius:圆的半径
* @param color:圆的颜色,规则根据B(蓝)G(绿)R(红)
* @param thickness:如果是正数,表示组成圆的线条的粗细程度。否则,-1表示圆是否被填充
* @param lineType:线条的类型。默认是8(8填充模式)
* @param shift:圆心坐标点和半径值的小数点位数
*/
Imgproc.circle(Mat img, Point center, int radius, Scalar color, int thickness, int lineType, int shift)

使用心得:
值得注意的参数:

  1. minDist
    相邻圆心之间的最小距离,减少重复圆
  2. param1
    canny边缘检测流程:
(1)高斯算子消除噪声
(2)计算梯度的幅值和方向
 分别用卷积计算x和y方向 的梯度,然后将两个方向的平方和开根号就是幅值,这个幅值很有用,在霍夫圆中将使用到。  
(3)非极大值抑制
(4)滞后阈值
 若某一像素的幅值超过了 高阈值,则该像素被保留为边缘像素。
 若某一像素的幅值小于 低阈值,该像素被排除。
 若某一像素的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高阈值 的像素是被保留。  

  霍夫圆中的阈值就是用来检测幅值的。因此在实际应用中,降低低阈值的数值,可以增加检测到的圆,增加低阈值将减少检测到的圆。增加高阈值的值,将减小检测到的圆,减小高阈值的值,将增加检测到的圆。

   霍夫检测对噪声比较敏感,因此需要先对图像进行降噪处理,比如中值滤波
   霍夫找圆程序很卡很慢时,一定要调高滞后阈值的最低值

2. 示例代码

//程序运行需导入 lib或so 文件,和相应的 opencv jar包
public static void main(String[] args){

    Mat src = Imgcodecs.imread("F:\\89226.jpg");
 
    Mat dst = src.clone();
    Imgproc.cvtColor(src, dst, Imgproc.COLOR_BGR2GRAY);
 
    Mat circles = new Mat();
	Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100, 600, 50, 0, 150);
    for (int i = 0; i < circles.cols(); i++)
    {
		double[] circle = circles.get(0, i);

		Point center = new Point(circle[0], circle[1]);
		int radius = (int) Math.round(circle[2]);
 
		// circle center
		Imgproc.circle(src, center, 3, new Scalar(0, 255, 0), -1, 8, 0);
		// circle outline
		Imgproc.circle(src, center, radius, new Scalar(0, 255, 0), 3, 8, 0);
    }
 
    Imgcodecs.imwrite("F:\\89226-2.jpg", src);
}

3. 演示结果

源图:
basketball-src
输出:
basketball-out

posted @ 2020-04-19 12:59  盐有点多  阅读(870)  评论(0编辑  收藏  举报