OpenCV检测图像轮廓


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


轮廓只不过是图像中连接的曲线,或者图像中连通部分的边界,轮廓通常以图像中的边缘来计算,但是,边缘和轮廓的区别在于轮廓是闭合的,而边缘可以是任意的。边缘的概念局限于点及其邻域像素,轮廓将目标作为整体进行处理。

效果图

效果图

原图

源码

KqwOpenCVFeaturesDemo

步骤

  1. 将图像置灰
  2. 使用Canny边缘检测检测出图像的边缘
  3. 调用Imgproc.findContours()方法检测图像轮廓
  4. 在新的图像上画出轮廓

封装

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
/**
* 找出轮廓
*
* @param bitmap 要检测的图片
*/
public void findContours(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 hierarchy = new Mat();
// 保存轮廓
ArrayList<MatOfPoint> contourList = new ArrayList<>();
// 检测轮廓
Imgproc.findContours(cannyEdges, contourList, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
// 画出轮廓
Mat contours = new Mat();
contours.create(cannyEdges.rows(), cannyEdges.cols(), CvType.CV_8UC3);
Random r = new Random();
for (int i = 0; i < contourList.size(); i++) {
Imgproc.drawContours(contours, contourList, i, new Scalar(r.nextInt(255), r.nextInt(255), r.nextInt(255), -1));
}
// Mat转Bitmap
Bitmap processedImage = Bitmap.createBitmap(contours.cols(), contours.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(contours, 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.findContours(mSelectImage);
坚持原创技术分享,您的支持将鼓励我继续创作!