opencv形态学应用之区域填充

来源:互联网 发布:ubuntu 设置密码 编辑:程序博客网 时间:2024/05/24 07:20

在进行形态学填充之前必须了解一点:当我们的边界是4连通边界时,我们使用的结构元素为8连通;当我们的连通边界为8连通时,我们需要用4连通的结构元素。


算法:

初始化:Bo=种子点(这里采用opencv鼠标操作来手动选取种子点)

循环:

(用3X3十字结构元素对对种子点进行膨胀,然后不断的用图像的补集对膨胀的结果进行约束)

结束条件:膨胀结果不发生变化

#include<opencv2\opencv.hpp>#include<iostream>using namespace std;using namespace cv;Point ptStart;/***************************************************功能:以ptStart为起点对图像进行填充参数:src-边界图像      ptStart-种子点的坐标****************************************************/void BoundarySeedFill(Mat &src, Point ptStart){Mat dst = Mat::zeros(src.size(), src.type());int se[3][3] = { { -1, 1, -1 }, { 1, 1, 1 }, { -1, 1, -1 } };//十字形结构元素Mat tempImg = Mat::ones(src.size(), src.type())*255;Mat revImg =tempImg - src;//原图像的补集dst.at<uchar>(ptStart.y, ptStart.x) = 255;//绘制种子点while (true)//循环膨胀图像直到图像不在产生变化{Mat temp;dst.copyTo(temp);dilate(dst, dst, se); //用十字结构元素膨胀dst = dst&revImg; //限制膨胀不会超过原始边界if (equalImg(dst, temp)) //不在变化时停止{break;}}src = dst;}void on_MouseHandle(int event, int x, int y, int flag, void* param){Mat& image = *(cv::Mat*)param;switch (event){case EVENT_LBUTTONDOWN:ptStart.x = x;ptStart.y = y;break;case EVENT_LBUTTONUP:BoundarySeedFill(image, ptStart);imshow("边界图像", image);break;}}int main(){//读取二值图像(此步可以忽略)Mat src = imread("test1.jpg", 0);imshow("原始图像", src);//创建模板int se[3][3] = { { -1, 1, -1 }, { 1, 1, 1 }, { 1, 1, 1 } };//区域填充setMouseCallback("边界图像", on_MouseHandle, (void*)&src);waitKey(0);return 0;}

原始图像:


填充结果:


原创粉丝点击