opencv之分水岭算法分割及图像修补

1)分水岭算法
原理:
任何一幅灰度图像都可以被看成是拓扑平面,灰度值高的区域可以被看成是山峰,灰度值低的区域可以被看成是山谷,我们向每一个山谷中灌不同颜色的水,随着水位的升高,不同山谷的水就会相遇汇合,为了防止不同山谷的水的汇合,我们需要在水汇合的地方构建起堤坝,不停的灌水,不停的构建堤坝直到所有的山峰都被水淹没,我们构建好的堤坝就是对图像的分割,这就是分水岭算法的背后原理
对灰度图的地形学解释,我们考虑三类点
1 局部最小值点,该点对应一个盆地里滴一滴水的时候,由于重力作用,水最终会汇聚到该点,注意,可能存在一个最小值面,该平面内都是最小值点
2 盆地的其他位置点,该位置滴的水滴会汇聚到局部最小点
3 盆地的边缘点,是该盆地和其他盆地交接点,在该点滴一滴水,会等概率的流向任何一个盆地


在真实图像中,由于噪声点或者其他干扰因素的存在,使用分水岭算法常常存在过度分割的现象,这是因为很多很小的局部极值点的存在
为了解决过度分割的问题,可以使用基于标记(mark)图像的分水岭算法,就是通过先验知识(常识),来指导分水岭算法,以便获得更好的图像分段效果,通常的mark图像,都是在某个区域定义了一些灰度层级,在这个区域的洪水淹没过程中,水平面都是从定义的高度开始的,这样可以避免一些很小的噪声极值区域的分割
就是开始从标记处分割


分水岭算法–watershed()
void watershed(InputArray image,InputOutputArray markers);
&&image:输入图像,需为8位三通道彩色图像
&&markers:参数调用后的结果,输入/输出32位单通道图像标记结果,需和原图一样的大小

Mat srcImg=imread("bird.jpg");
imshow("src",srcImg);
Mat dstImg=srcImg.clone();
//medianBlur(srcImg,srcImg,5);
//GaussianBlur(srcImg,srcImg,Size(5,5),0,0);
Mat imgMask(srcImg.size(),CV_8U,Scalar(0));
//标记背景图像
rectangle(imgMask,Point(1,1),Point(srcImg.cols-2,srcImg.row-2),Scalar(255),1);
//标记鸟       画图工具框出坐标
recctangle(imgMask,Point(srcImg.cols/2-10,srcImg.rows/2-10),Point(srcImg.cols/2+10,srcImg.rows/2+10),CV::Scalar(128),10);
//标记岩石
rectangle(imgMask,Point(264,353),Point(314,395),cv::Scalar(64),10);
imshow("mask",imgMask);
imgMask.convertTo(imgMask,CV_32S);//转化类型
watershed(srcImg,imgMask);
Mat mark1,mark2;
imgMask.convertTo(mark1,CV_8U);
imshow("marker",mark1);

图像修补
Opencv中图像修补技术由inpaint函数实现,基本步骤是先修复区域边缘再逐步向内推进修复,可以用来清除照片灰尘,划痕,或者从静态图像及视频中去除不需要的物体
图像修补—inpaint()
void inpaint(InputArray src,InputArray inpaintMask,OutputArray dst,double inpaintRadius,int flags);
&& src:输入图像,需为8位单通道或三通道色图像
&&inpainMask:修复掩膜,为8位单通道图像,其中非0像素表示需要修补的区域
&&dst:函数调用后输出图像,和原图一样的尺寸和类型
&&InpaintRadius:需要修补的每个点的圆形邻域,为修复算法的参考半径
&&flags:修补方法的标识符
INPAINT_NS=CV_INPAINT_NS,
INPAINT_TELEA=CV_INPAINT_TELEA
基于Navier_Stokes方程方法和Alexandru Telea
注:需要添加opencv_photo248d.lib与photo.hpp

属性管理器 链接器opencv_photo248d.lib


猜你喜欢

转载自blog.csdn.net/xujaiwei/article/details/74518494