霍夫线变换
霍夫线变换是一种在图像中寻找直线的方法。OpenCV中支持三种霍夫线变换,分别是标准霍夫线变换、多尺度霍夫线变换、累计概率霍夫线变换。
在OpenCV中可以调用函数HoughLines来调用标准霍夫线变换和多尺度霍夫线变换。HoughLinesP函数用于调用累积概率霍夫线变换。
我们都知道,二维坐标轴上表示一条直线的方程式y = a*x + b,我们想求出一条直线就得想方设法求出其中的a和b的值。如果用极坐标来表示就是
theta就是直线与水平线所成的角度,而rho就是圆的半径(也可以理解为原点到直线的距离),同样地,这两个参数也是表征一条直线的重要参数,确定他们俩了,也就确定一条直线了。正如下图所示。
在OpenCV里,我们只需调用HoughLines就是可以得到表征一条直线的这两个参数值!
标准hough变换:
Imgproc.HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn, double min_theta, double max_theta)
参数说明:
image:源图像
lines:hough变换后储存检测到的线条的输出矢量
rho:以像素为单位的距离精度
theta:以弧度为单位的角度精度
threshold:识别某部分为一条直线时必须达到的值
srn:rho参数的除数距离,有默认值0
stn:theta参数的除数距离,默认值0
min_theta:检测到的直线的最小角度
max_theta:检测到的直线的最大角度
HoughLines代码
public static void main(String[] args) {
System.load("F:\\opencv\\x64\\opencv_java401.dll");
Mat src = Imgcodecs.imread("C:\\Users\\beawan\\Desktop\\test\\test.jpg");
Mat canny = new Mat();
Imgproc.Canny(src, canny, 50, 200, 3);
Mat storage = new Mat();
//这里注意第五个参数,表示阈值,阈值越大,表明检测的越精准,速度越快,得到的直线越少(得到的直线都是很有把握的直线)
//这里得到的lines是包含rho和theta的,而不包括直线上的点,所以下面需要根据得到的rho和theta来建立一条直线
Imgproc.HoughLines(canny, storage, 1, Math.PI / 180, 150, 0, 0, 0, 10);
for (int x = 0; x < storage.rows(); x++) {
double[] vec = storage.get(x, 0);
double rho = vec[0]; //就是圆的半径r
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;
int lineLength = 1000;
pt1.x = Math.round(x0 + lineLength * (-b));
pt1.y = Math.round(y0 + lineLength * (a));
pt2.x = Math.round(x0 - lineLength * (-b));
pt2.y = Math.round(y0 - lineLength * (a));
if (theta >= 0) {
Imgproc.line(src, pt1, pt2, new Scalar(255, 0, 0), 1, Imgproc.LINE_4, 0);
}
}
Imgcodecs.imwrite("C:\\Users\\beawan\\Desktop\\test\\houghLines.jpg", src);
}
图片
直线
累计概率hough变换:
Imgproc.HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap)
参数说明:
image:源图像
lines:hough变换后储存检测到的线条的输出矢量
rho:以像素为单位的距离精度
theta:以弧度为单位的角度精度
threshold:识别某部分为一条直线时必须达到的值
minLineLength:最低线段的长度,默认为0
maxLineGap:允许将同一行点与点之间连接起来的最大的距离,默认为0
public static void main(String[] args) {
System.load("F:\\opencv\\x64\\opencv_java401.dll");
Mat src = Imgcodecs.imread("C:\\Users\\beawan\\Desktop\\test\\test.jpg");
Mat canny = new Mat();
Imgproc.Canny(src, canny, 50, 200, 3);
Mat storage = new Mat();
Imgproc.HoughLinesP(canny, storage, 1, Math.PI / 180, 200, 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(src, start, end, new Scalar(255, 0, 0), 5, Imgproc.LINE_4, 0);
}
Imgcodecs.imwrite("C:\\Users\\beawan\\Desktop\\test\\houghLinesP.jpg", src);
}
直线