做网站都需要什么,金融门户网站模版,哪个网站可以做免费商业推广,九脉堂是做网站的原理介绍
前面写了OTSU算法、最大熵算法、自适应阈值法、基于区域生长算法。他们都有各自的优缺点#xff0c;而分水岭算法具有它们都具有的优势#xff0c;所以通常能够产生更加稳健的分割效果。
分水岭算法(watershed)是一种比较基本的数学形态学分割算法#xff0c;其基…原理介绍
前面写了OTSU算法、最大熵算法、自适应阈值法、基于区域生长算法。他们都有各自的优缺点而分水岭算法具有它们都具有的优势所以通常能够产生更加稳健的分割效果。
分水岭算法(watershed)是一种比较基本的数学形态学分割算法其基本思想是将灰度图像转换为梯度图像将梯度值看作高低起伏的山岭将局部极小值及其邻域看作一个“集水盆”。设想一个个“集水盆”中存在积水且水位不断升高淹没梯度较低的地方当水漫过程停止后就找出了分割线图像也就可以被分割成几块连通区域。这里用动图演示一下 所以寻找局部极小值是算法的关键但在真实图像中由于噪声点或者其它干扰因素的存在使用分水岭算法常常存在过度分割的现象这是因为很多很小的局部极值点的存在比如下面的图像这样的分割效果是毫无用处的 为了解决过度分割的问题可以使用基于标记(mark)图像的分水岭算法就是通过先验知识来指导分水岭算法以便获得更好的图像分段效果。通常的mark图像都是在某个区域定义了一些灰度层级在这个区域的洪水淹没过程中水平面都是从定义的高度开始的这样可以避免一些很小的噪声极值区域的分割。
标记(mark)可以通过人工交互标记也可以通过计算。下面展示了采用基于mark的分水岭算法过程第一幅图红色区域就是标记的灰度级。 通过标记我们可以得到很好得分割效果 OpenCV接口
void watershed( InputArray image, InputOutputArray markers ); 输入图像必须是3通道的RGB图像最为关键的是第二个参数markers这个参数包含不同区域的轮廓每个轮廓有一个自己唯一的编号轮廓的定位可以通过Opencv中findContours方法实现。然后分水岭算法会根据markers传入的标记作为种子也就是所谓的注水点、标记点对图像上其他的像素点根据分水岭算法规则进行判断并对每个像素点的区域归属进行划定直到处理完图像上所有像素点。而区域与区域之间的分界处的值被置为“-1”以做区分。
OpenCV的官方示例https://docs.opencv.org/3.4.0/d8/da9/watershed_8cpp-example.html 示例代码
#include opencv2/core/utility.hpp
#include opencv2/imgproc.hpp
#include opencv2/imgcodecs.hpp
#include opencv2/highgui.hpp
#include cstdio
#include iostream
using namespace cv;
using namespace std;
static void help()
{cout \nThis program demonstrates the famous watershed segmentation algorithm in OpenCV: watershed()\nUsage:\n./watershed [image_name -- default is ../data/fruits.jpg]\n endl;cout Hot keys: \n\tESC - quit the program\n\tr - restore the original image\n\tw or SPACE - run watershed segmentation algorithm\n\t\t(before running it, *roughly* mark the areas to segment on the image)\n\t (before that, roughly outline several markers on the image)\n;
}
Mat markerMask, img;
Point prevPt(-1, -1);
static void onMouse(int event, int x, int y, int flags, void*)
{if (x 0 || x img.cols || y 0 || y img.rows)return;if (event EVENT_LBUTTONUP || !(flags EVENT_FLAG_LBUTTON))prevPt Point(-1, -1);else if (event EVENT_LBUTTONDOWN)prevPt Point(x, y);else if (event EVENT_MOUSEMOVE (flags EVENT_FLAG_LBUTTON)){Point pt(x, y);if (prevPt.x 0)prevPt pt;line(markerMask, prevPt, pt, Scalar::all(255), 1, 8, 0);line(img, prevPt, pt, Scalar::all(255), 1, 8, 0);prevPt pt;imshow(image, img);}
}
int main(int argc, char** argv)
{cv::CommandLineParser parser(argc, argv, {help h | | }{ input | I:/Learning-and-Practice/2019Change/Image process algorithm/Img/lung2.jpeg | });if (parser.has(help)){help();return 0;}string filename parser.getstring(input);Mat img0 imread(filename, 1), imgGray;if (img0.empty()){cout Couldng open image filename . Usage: watershed image_name\n;return 0;}help();namedWindow(image, 1);img0.copyTo(img);cvtColor(img, markerMask, COLOR_BGR2GRAY);cvtColor(markerMask, imgGray, COLOR_GRAY2BGR);markerMask Scalar::all(0);imshow(image, img);setMouseCallback(image, onMouse, 0);for (;;){char c (char)waitKey(0);if (c 27)break;if (c r){markerMask Scalar::all(0);img0.copyTo(img);imshow(image, img);}if (c w || c ){int i, j, compCount 0;vectorvectorPoint contours;vectorVec4i hierarchy;findContours(markerMask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);if (contours.empty())continue;Mat markers(markerMask.size(), CV_32S);markers Scalar::all(0);int idx 0;for (; idx 0; idx hierarchy[idx][0], compCount)drawContours(markers, contours, idx, Scalar::all(compCount 1), -1, 8, hierarchy, INT_MAX);if (compCount 0)continue;vectorVec3b colorTab;for (i 0; i compCount; i){int b theRNG().uniform(0, 255);int g theRNG().uniform(0, 255);int r theRNG().uniform(0, 255);colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));}double t (double)getTickCount();Mat tmp Mat::zeros(markers.size(), CV_8U);markers.convertTo(tmp, CV_8U, 255);imshow(markers,tmp);watershed(img0, markers);t (double)getTickCount() - t;printf(execution time %gms\n, t*1000. / getTickFrequency());Mat wshed(markers.size(), CV_8UC3);// paint the watershed imagefor (i 0; i markers.rows; i)for (j 0; j markers.cols; j){int index markers.atint(i, j);if (index -1)wshed.atVec3b(i, j) Vec3b(255, 255, 255); //边界else if (index 0 || index compCount)wshed.atVec3b(i, j) Vec3b(0, 0, 0);elsewshed.atVec3b(i, j) colorTab[index - 1];}wshed wshed*0.5 imgGray*0.5;imshow(watershed transform, wshed);}}return 0;
}
效果 标记 原图标记 分割效果 参考
http://www.cnblogs.com/mikewolf2002/p/3304118.html
https://www.cnblogs.com/zyly/p/9392881.html#_label2
http://m.itboth.com/d/6Zv2ue/opencv-c
https://blog.csdn.net/just_sort/article/details/87376355
https://docs.opencv.org/3.4.0/d8/da9/watershed_8cpp-example.html