OpenCV计算机图像视觉基础学习笔记13——轮廓发现

正片开始!

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法。所以边缘提取的阈值选定会影响最终轮廓发现结果。轮廓与边缘的概念是非常相似的,但是也不完全一致。


简单测试

可能会用到的API:

findContours发现轮廓 在灰度图像上发现轮廓

drawContours绘制轮廓 根据发现的轮廓把它绘制出来

在二值图像上发现轮廓使用APIcv::findContours

1
2
3
4
5
6
7
8
9
10
11
findContours(
InputOutputArray binImg,
// 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit
OutputArrayOfArrays contours,
// 全部发现的轮廓对象
OutputArray, hierachy
// 图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。
int mode, // 轮廓返回的模式
int method,// 发现方法
Point offset=Point()// 轮廓像素的位移,默认(0, 0)没有位移
)

在二值图像上发现轮廓使用API cv::findContours之后对发现的轮廓数据进行绘制显示

1
2
3
4
5
6
7
8
9
10
11
drawContours(
InputOutputArray binImg, // 输出图像
OutputArrayOfArrays contours,// 全部发现的轮廓对象
Int contourIdx// 轮廓索引号
const Scalar & color,// 绘制时候颜色
int thickness,// 绘制线宽
int lineType ,// 线的类型LINE_8
InputArray hierarchy,// 拓扑结构图
int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓
Point offset=Point()// 轮廓位移,可选
)

做法是这样的:

  • 输入图像转化为灰度图
  • 使用Canny算法进行边缘检测,得到二值图像
  • 使用findContours寻找轮廓
  • 使用drawContours绘制轮廓

感觉自己手里的图不是太适合拿来做检测,毕竟插画都太花里胡哨。这次我直接拿工业相机拍下的离心机内部照片做测试。尝试采用第二种方案,去掉二维码检测边缘(第一种方案为重新贴二维码,暂时不考虑)。

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
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#define debug cout << "ok" << endl;

using namespace cv;
using namespace std;
Mat src, gsrc, dst;
int threshold_value = 50;
int max_value = 255;
const char* output_win = "Final Result";
const char* input_win = "src image";

void demo_contours(int, void*) {
Mat cannyOutPut;
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
Canny(gsrc, cannyOutPut, threshold_value, threshold_value * 2, 3, false);
findContours(cannyOutPut, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

dst = Mat::zeros(src.size(), CV_8UC3);
RNG rng(12345);
for (size_t i = 0; i < contours.size(); i++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
}
imshow(output_win, dst);
}

int main() {
src = imread("D:/pic6.png");
if (!src.data) {
cout << "could not load image..." << endl;
return -1;
}
namedWindow(output_win, CV_WINDOW_AUTOSIZE);
imshow(input_win, src);
cvtColor(src, gsrc, CV_BGR2GRAY);

const char* trackBarTitle = "Threshold Value";
createTrackbar(trackBarTitle, output_win, &threshold_value, max_value, demo_contours);
demo_contours(0, 0);

waitKey(0);
return 0;
}

嗯,检测轮廓还是比较有效果的,只是它现在线条还比较乱。

也许学了后面的绘制矩形框和圆形框就可以定位出矩形了。

此后的操作便是求出矩形的中心坐标,传给机器,就完成目标了。

慢慢来,加油。


-------------本文结束,感谢您的阅读转载请注明原作者及出处-------------


本文标题:OpenCV计算机图像视觉基础学习笔记13——轮廓发现

文章作者:Shawn Zhou

发布时间:2019年08月31日 - 14:08

最后更新:2019年08月31日 - 16:08

原始链接:http://shawnzhou.xyz/2019/08/31/19-08-31-03/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

知识无价,码字不易。对您有用,敬请打赏。金额随意,感谢关心。
0%