hough变换是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合特定形状的集合作为hough变换结果。
发展史:
1962年由PaulHough首次提出,用来检测直线和曲线。
1972年由Richard Duda & Peter Hart推广使用,扩展到任意形状物体的识别。
原理:
一条直线在直角坐标系下的表示形式为y=k*x+b,而在极坐标系下表示为r=x*cos(theta)+y*sin(theta)。hough变换的思想为在直角坐标系下的一个点对应极坐标系下的一条直线,同样,极坐标系下的一个点对应直角坐标系下的一条直线。在直角坐标系中的直线,斜率和截距是一定的,这样这条直线上的所有点在极坐标系中聚焦于一点,这样的聚焦点就代表了直角坐标系中的直线。
对于直线x=c,在实际应用中,是采用参数方程p=x*cos(theta)+y*sin(theta)。这样,图像平面上的一个点就对应到参数r—theta平面上的一条曲线上,其它的还是一样。
标准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:检测到的直线的最大角度
示例代码:
public static void main(String[] args)
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat srcImage = Imgcodecs.imread("F:\\6597210504144579394.jpg");
Mat dstImage = srcImage.clone();
Imgproc.Canny(srcImage, dstImage, 400, 500, 5, false);
Mat storage = new Mat();
Imgproc.HoughLines(dstImage, storage, 1, Math.PI / 180, 200, 0, 0, 0, 10);
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));
if (theta >= 0)
{
Imgproc.line(srcImage, pt1, pt2, new Scalar(255, 255, 255, 255), 1, Imgproc.LINE_4, 0);
}
}
Imgcodecs.imwrite("F:\\dst2.jpg", srcImage);
}
累计概率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.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat srcImage = Imgcodecs.imread("F:\\6597210504144579394.jpg");
Mat dstImage = srcImage.clone();
Imgproc.Canny(srcImage, dstImage, 400, 500, 5, false);
Mat storage = new Mat();
Imgproc.HoughLinesP(dstImage, 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(srcImage, start, end, new Scalar(255, 255, 255, 255), 1, Imgproc.LINE_4, 0);
}
Imgcodecs.imwrite("F:\\dst2.jpg", srcImage);
}