C/C++ 图像处理(14)------图像の轮廓填充
2016-11-25 16:03
351 查看
所谓图像的轮廓填充,是建立在图像的轮廓已然查找完成的情况下的,以下面图像为例:
我们首先需要查找到图像中的圆形和正方形的几个轮廓,之后才能对这些轮廓进行处理(查找的过程我们用到OpenCV的findContours函数)。
在得到轮廓之后,难点就转变为如何填充轮廓了,对于左上角的圆来说,直接填充即可,然而对于圆环和“田”字,则一般只希望填充两个轮廓直接的区域,中间的孔洞则保留,因此在对轮廓进行填充之前需要做进一步的判断工作(通过判断findContours函数的第三个参数对象实现),具体的实现代码如下:
通过上面的代码,我们把图像中的轮廓进行了白色的填充,结果如下图所示
到此,我们得到了一副轮廓填充完成的图像,其中的填充区域为白色,如果需要进一步处理,则可以通过连通域检测算法找到各个轮廓像素点的集合。
需要注意的是,上面的代码只支持到两层轮廓的嵌套(一般而言,对于CAD等软件出来的图形最多只会有两层),再多层的嵌套则需要修改代码中的判断部分。
我们首先需要查找到图像中的圆形和正方形的几个轮廓,之后才能对这些轮廓进行处理(查找的过程我们用到OpenCV的findContours函数)。
在得到轮廓之后,难点就转变为如何填充轮廓了,对于左上角的圆来说,直接填充即可,然而对于圆环和“田”字,则一般只希望填充两个轮廓直接的区域,中间的孔洞则保留,因此在对轮廓进行填充之前需要做进一步的判断工作(通过判断findContours函数的第三个参数对象实现),具体的实现代码如下:
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "time.h" using namespace cv; using namespace std; int main(int argc, char** argv) { long time = clock(); int r = 100; Mat src = Mat::zeros(Size(8 * r, 4 * r), CV_8UC1); //绘制轮廓,因为线段本身有粗细,则绘制一个圆会检测出两个轮廓,需要特别注意 //绘制三个圆,其中一个嵌套着另一个 circle(src, cvPoint(2 * r, 2 * r), 80, Scalar(255), 2); circle(src, cvPoint(2 * r, 2 * r), 50, Scalar(255), 2); circle(src, cvPoint(r, r), 30, Scalar(255), 2); //绘制一个田字 rectangle(src, cvPoint(4 * r - r / 2, 2 * r - r / 2), cvPoint(4 * r + r / 2, 2 * r + r / 2), Scalar(255), 2); rectangle(src, cvPoint(4 * r - r * 2 / 5, 2 * r - r * 2 / 5), cvPoint(4 * r - r * 1 / 20, 2 * r - r * 1 / 20), Scalar(255), 2); rectangle(src, cvPoint(4 * r - r * 2 / 5, 2 * r + r * 1 / 20), cvPoint(4 * r - r * 1 / 20, 2 * r + r * 2 / 5), Scalar(255)); rectangle(src, cvPoint(4 * r + r * 2 / 5, 2 * r - r * 2 / 5), cvPoint(4 * r + r * 1 / 20, 2 * r - r * 1 / 20), Scalar(255), 2); rectangle(src, cvPoint(4 * r + r * 2 / 5, 2 * r + r * 1 / 20), cvPoint(4 * r + r * 1 / 20, 2 * r + r * 2 / 5), Scalar(255), 2); Mat raw_dist1(src.size(), CV_32FC1); vector<vector<Point> > contours; vector<Vec4i> hierarchy; Mat src_copy = src.clone(); findContours(src_copy, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);//查找轮廓,并以树状图结果存储轮廓信息 for (size_t i = 0; i < contours.size(); i++) { if (hierarchy[i][3] != -1)//表示其为某一个轮廓的内嵌轮廓 { if (hierarchy[hierarchy[i][3]][3] == -1)//表示其为最外层轮廓,上面检测到的是其线条的内部 { drawContours(raw_dist1, contours, i, Scalar(255), -1); } else { drawContours(raw_dist1, contours, i, Scalar(0), -1); } } else { drawContours(raw_dist1, contours, i, Scalar(0), -1); } } printf("花费时间%dms\n", clock() - time); char* source_window = "Source"; namedWindow(source_window, CV_WINDOW_AUTOSIZE); imshow(source_window, src); namedWindow("Distance1", CV_WINDOW_AUTOSIZE); imshow("Distance1", raw_dist1); imwrite("轮廓查找图像.jpg", src); imwrite("轮廓查找完成图像.jpg", raw_dist1); waitKey(0); return(0); }
通过上面的代码,我们把图像中的轮廓进行了白色的填充,结果如下图所示
到此,我们得到了一副轮廓填充完成的图像,其中的填充区域为白色,如果需要进一步处理,则可以通过连通域检测算法找到各个轮廓像素点的集合。
需要注意的是,上面的代码只支持到两层轮廓的嵌套(一般而言,对于CAD等软件出来的图形最多只会有两层),再多层的嵌套则需要修改代码中的判断部分。
相关文章推荐
- C/C++ 图像处理(16)------图像轮廓の最小外接矩形
- C++图像处理 -- 线性亮度/对比度调整
- Symbian c++调用opencv库进行图像处理
- C++图像处理 -- 图像黑白调整应用
- C++图像处理 -- 图像合成
- C++图像处理 -- 亮度/对比度调整
- Delphi图像处理 -- 填充浮雕
- 【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现
- C++图像处理 -- 图像颜色混合(下)
- C++图像处理 -- 图像颜色混合(中)
- C++图像处理 -- 数据类型及公用函数
- c++图像处理
- 数字图像处理编成入门笔记——第7章 边沿检测与提取,轮廓跟踪
- 图像内轮廓填充
- 【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现
- C++图像处理类
- C++实现基础图像处理
- C++图像处理 -- 平面几何变换类
- C++中把线形存储的像素转化为二维数组形式,做图像增前处理
- C++图像处理 -- 文章索引