OpenCV使用霍夫变换检测图像中的形状


转载请说明出处!
作者:kqw攻城狮
出处:个人站 | CSDN


霍夫变换是一种被广泛使用的利用数学等式的参数形式在图像中检测形状的技术。
例如直线、椭圆、圆等形状。

霍夫变换可以检测任何能以参数形式表示的形状,随着形状的复杂(维数的增加,例如球体),计算的消耗也会增加。
我们通常只考虑简单的霍夫形状,例如直线和圆。

源码

KqwOpenCVFeaturesDemo

霍夫直线

效果图

效果图

原图

步骤

  1. 将图像置灰
  2. 调用Imgproc.HoughLinesP(cannyEdges, lines, 1, Math.PI / 180, 50, 20, 20) 方法获取直线的数据

    • 第一个参数:图像输入
    • 第二个参数:图像输出
    • 第三个参数:图像指定像素中r的解析度
    • 第四个参数:图像指定像素中θ的解析度
    • 第五个参数:直线上点数的阈值
    • 第六个参数:直线上点数的最小值
  3. 在图像上绘制直线

封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* 霍夫直线
*
* @param bitmap 要检测的图片
*/
public void houghLines(Bitmap bitmap) {
if (null != mSubscriber)
Observable
.just(bitmap)
// 检测边缘
.map(new Func1<Bitmap, Mat>() {
@Override
public Mat call(Bitmap bitmap) {
Mat grayMat = new Mat();
Mat cannyEdges = new Mat();
// Bitmap转为Mat
Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4);
Utils.bitmapToMat(bitmap, src);
// 原图置灰
Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY);
// Canny边缘检测器检测图像边缘
Imgproc.Canny(grayMat, cannyEdges, 10, 100);
return cannyEdges;
}
})
// 霍夫直线
.map(new Func1<Mat, Bitmap>() {
@Override
public Bitmap call(Mat cannyEdges) {
Mat lines = new Mat();
Imgproc.HoughLinesP(cannyEdges, lines, 1, Math.PI / 180, 50, 20, 20);
Mat houghLines = new Mat();
houghLines.create(cannyEdges.rows(), cannyEdges.cols(), CvType.CV_8UC1);
// 在图像上画直线
for (int i = 0; i < lines.cols(); i++) {
double[] points = lines.get(0, i);
double x1, y1, x2, y2;
x1 = points[0];
y1 = points[1];
x2 = points[2];
y2 = points[3];
Point pt1 = new Point(x1, y1);
Point pt2 = new Point(x2, y2);
// 绘制直线
Core.line(houghLines, pt1, pt2, new Scalar(255, 0, 0), 1);
}
// Mat转Bitmap
Bitmap processedImage = Bitmap.createBitmap(houghLines.cols(), houghLines.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(houghLines, processedImage);
return processedImage;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(mSubscriber);
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 图片特征提取的工具类
mFeaturesUtil = new FeaturesUtil(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
// 图片处理完成
dismissProgressDialog();
}
@Override
public void onError(Throwable e) {
// 图片处理异常
dismissProgressDialog();
}
@Override
public void onNext(Bitmap bitmap) {
// 获取到处理后的图片
mImageView.setImageBitmap(bitmap);
}
});
// 霍夫直线
mFeaturesUtil.houghLines(mSelectImage);

霍夫圆

效果图

效果图

原图

步骤

霍夫圆与霍夫直线类似,只是等式改变了,调用

1
Imgproc.HoughCircles(cannyEdges, circles, Imgproc.CV_HOUGH_GRADIENT, 1, cannyEdges.rows() / 15);

获取圆的数据

封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* 霍夫圆
*
* @param bitmap 要检测的图片
*/
public void houghCircles(Bitmap bitmap) {
if (null != mSubscriber)
Observable
.just(bitmap)
// 检测边缘
.map(new Func1<Bitmap, Mat>() {
@Override
public Mat call(Bitmap bitmap) {
Mat grayMat = new Mat();
Mat cannyEdges = new Mat();
// Bitmap转为Mat
Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4);
Utils.bitmapToMat(bitmap, src);
// 原图置灰
Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY);
// Canny边缘检测器检测图像边缘
Imgproc.Canny(grayMat, cannyEdges, 10, 100);
return cannyEdges;
}
})
// 霍夫圆
.map(new Func1<Mat, Bitmap>() {
@Override
public Bitmap call(Mat cannyEdges) {
Mat circles = new Mat();
Imgproc.HoughCircles(cannyEdges, circles, Imgproc.CV_HOUGH_GRADIENT, 1, cannyEdges.rows() / 15);
Mat houghCircles = new Mat();
houghCircles.create(cannyEdges.rows(), cannyEdges.cols(), CvType.CV_8UC1);
// 在图像上画圆
for (int i = 0; i < circles.cols(); i++) {
double[] parameters = circles.get(0, i);
double x, y;
int r;
x = parameters[0];
y = parameters[1];
r = (int) parameters[2];
// 绘制圆
Point center = new Point(x, y);
Core.circle(houghCircles, center, r, new Scalar(255, 0, 0), 1);
}
// Mat转Bitmap
Bitmap processedImage = Bitmap.createBitmap(houghCircles.cols(), houghCircles.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(houghCircles, processedImage);
return processedImage;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(mSubscriber);
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 图片特征提取的工具类
mFeaturesUtil = new FeaturesUtil(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
// 图片处理完成
dismissProgressDialog();
}
@Override
public void onError(Throwable e) {
// 图片处理异常
dismissProgressDialog();
}
@Override
public void onNext(Bitmap bitmap) {
// 获取到处理后的图片
mImageView.setImageBitmap(bitmap);
}
});
// 霍夫圆
mFeaturesUtil.houghCircles(mSelectImage);
坚持原创技术分享,您的支持将鼓励我继续创作!