java调用opencv霍夫线变换

314 阅读3分钟

1.HoughLines

image.png

public static void houghLines(Mat image){

Mat clone=image.clone();
Imgproc.GaussianBlur(clone, clone, new Size(3, 3), 0, 0);
//HighGui.imshow("GaussianBlur", clone);

Imgproc.cvtColor(clone, clone,Imgproc.COLOR_BGR2GRAY);
//HighGui.imshow("GRY", clone);
//一般来说,高阈值maxVal推荐是低阈值minVal的2~3倍
int lowThresh=20;
////边缘检测
Imgproc.Canny(clone, clone,lowThresh, lowThresh*3,3);
//HighGui.imshow("Canny", clone);

Mat storage = new Mat();
/**
 * HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn, double min_theta, double max_theta)
 * image 原图
 * lines 霍夫线变换检测到线条的输出矢量,由(ρ,θ)表示
 * rho   以像素为单位的距离精度(直线搜索时的进步尺寸的单位半径)
 * theta 以弧度为单位的角度精度(直线搜索时的进步尺寸的角度单位)
 * threshold 累加平面的阈值参数(直线被识别时它在累加平面中必须达到的值)
 * srn    对于多尺度霍夫变换,这是第三个参数进步尺寸的除数距离。
  *        粗略累加器进步尺寸直接是rho,精确的累加器进步尺寸为rho/srn
 * min_theta 检测到的直线的最小角度
 * max_theta 测到的直线的最大角度
*/
Imgproc.HoughLines(clone, storage, 1, Math.PI/ 180.0, 200, 0, 0);
for (int x = 0; x < storage.rows(); x++) {
	double[] vec = storage.get(x, 0);

	double rho = vec[0];
	double theta = vec[1];

	Point pt1 = new Point();
	Point pt2 = new Point();

	double a = Math.cos(theta);
	double b = Math.sin(theta);

	double x0 = a * rho;
	double y0 = b * rho;

	pt1.x = Math.round(x0 + 1000 * (-b));
	pt1.y = Math.round(y0 + 1000 * (a));
	pt2.x = Math.round(x0 - 1000 * (-b));
	pt2.y = Math.round(y0 - 1000 * (a));
	Imgproc.line(image, pt1, pt2, new Scalar(0, 0, 255), 1, Imgproc.LINE_4, 0);
}

HighGui.imshow("houghLines", image);
}

2.HoughLinesP

image.png

public static void houghLinesP(Mat image){
Mat clone=image.clone();
Imgproc.GaussianBlur(clone, clone, new Size(3, 3), 0, 0);
//HighGui.imshow("GaussianBlur", clone);

Imgproc.cvtColor(clone, clone,Imgproc.COLOR_BGR2GRAY);
//HighGui.imshow("GRY", clone);
//一般来说,高阈值maxVal推荐是低阈值minVal的2~3倍
int lowThresh=20;
////边缘检测
Imgproc.Canny(clone, clone,lowThresh, lowThresh*3,3);
//HighGui.imshow("Canny", clone);
Mat storage = new Mat();
/**
 * HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap)
 * image 原图
 * lines 霍夫线变换检测到线条的输出矢量,由(ρ,θ)表示
 * rho   以像素为单位的距离精度(直线搜索时的进步尺寸的单位半径)
 * theta 以弧度为单位的角度精度(直线搜索时的进步尺寸的角度单位)
 * threshold 累加平面的阈值参数(直线被识别时它在累加平面中必须达到的值)
 * minLineLength 最低线段的长度,比它短的线段不能被显示出来。
 * maxLineGap 允许将同一行点与点之间连接起来的最大距离
 */
Imgproc.HoughLinesP(clone, storage,  1, Math.PI / 180, 50, 0, 0);
for (int x = 0; x < storage.rows(); x++)
{
    double[] vec = storage.get(x, 0);
    double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
    Point start = new Point(x1, y1);
    Point end = new Point(x2, y2);
    Imgproc.line(image, start, end, new Scalar(0, 0, 255, 255), 1, Imgproc.LINE_4, 0);
}
HighGui.imshow("HoughLinesP", image); 
}

3.HoughCircles

image.png

public static void houghCircles(Mat image){
 Mat dst = image.clone();
 Imgproc.cvtColor(image, dst, Imgproc.COLOR_BGR2GRAY);

 Mat circles = new Mat();
 /**
  * HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius)
  * image 原图
  * circles 检测到的圆的输出矢量,每个矢量由(x,y,radius)表示
  * method 检测方法,填HOUGH_GRADIENT即可
  * dp 用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,
              允许创建一个比输入图像分辨率低的累加器。
               若dp=2,则累加器由输入图像一半大的宽度和高度)
  * minDist 霍夫变换检测到的圆的圆心之间的最小距离
  * param1  传给canny算子的高阈值,而低阈值为高阈值的一半
  * param2 在检测阶段圆心的累加器阈值
                       越小越可以检测不存在的圆,越大检测的圆更接近完美的圆形
  * minRadius 圆半径的最小值
  * maxRadius 圆半径的最大值
  */
 Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100, 440, 50, 0, 345);
 // Imgproc.HoughCircles(dst, circles, Imgproc.HOUGH_GRADIENT, 1, 100,
 // 440, 50, 0, 0);
 for (int i = 0; i < circles.cols(); i++)
 {
     double[] vCircle = circles.get(0, i);
     Point center = new Point(vCircle[0], vCircle[1]);
     int radius = (int) Math.round(vCircle[2]);
     // circle center
     Imgproc.circle(image, center, 3, new Scalar(0, 255, 0), -1, 8, 0);
     // circle outline
     Imgproc.circle(image, center, radius, new Scalar(0, 0, 255), 3, 8, 0);
 }
HighGui.imshow("HoughCircles", image); 
}