![7ccf6042bbb685fef07a4b371c2e96dd.png](https://img-blog.csdnimg.cn/img_convert/7ccf6042bbb685fef07a4b371c2e96dd.png)
1. 分水岭分割方法
它是依赖于形态学的,图像的灰度等级不一样,如果图像的灰度等级一样的情况下怎么人为的把它造成不一样?可以通过距离变换实现,这样它们的灰度值就有了阶梯状的变换。风水岭算法常见的有三种方法:(1)基于浸泡理论的分水岭分割方法;(2)基于连通图方法;(3)基于距离变换的方法。OpenCV 中是基于距离变换的分割方法,就相当于我们的小山头(认为造成的)。
基本的步骤:
![33a779960cbda5c182f0e2029a7d142c.png](https://img-blog.csdnimg.cn/img_convert/33a779960cbda5c182f0e2029a7d142c.png)
例子1 粘连对象分离和计数。
例子代码:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void test()
{
Mat srcImg;
srcImg = imread("pill_002.png");
if (srcImg.empty())
{
cout << "could not load image...n" << endl;
}
namedWindow("Original image", CV_WINDOW_AUTOSIZE);
imshow("Original image", srcImg);
Mat grayImg, binaryImg, shiftedImg;
//做滤波,使图像更加平滑,保留边缘,类似于双边滤波
pyrMeanShiftFiltering(srcImg, shiftedImg, 21, 51);
namedWindow("shifted", CV_WINDOW_AUTOSIZE);
imshow("shifted", shiftedImg);
cvtColor(shiftedImg, grayImg, COLOR_BGR2GRAY); //转为灰度图像
//二值化
threshold(grayImg, binaryImg, 0, 255, THRESH_BINARY | THRESH_OTSU);
namedWindow("binary", CV_WINDOW_AUTOSIZE);
imshow("binary", binaryImg);
//距离变换
Mat distImg;
distanceTransform(binaryImg, distImg, DistanceTypes::DIST_L2, 3, CV_32F);
//归一化,因为距离变换后得出来的值都比较小。
normalize(distImg, distImg, 0, 1, NORM_MINMAX);
namedWindow("distance", CV_WINDOW_AUTOSIZE);
imshow("distance", distImg);
//这个二值化的作用是寻找局部最大。
threshold(distImg, distImg, 0.4, 1, THRESH_BINARY);
namedWindow("distance_binary", CV_WINDOW_AUTOSIZE);
imshow("distance_binary", distImg);
//生成 marker
Mat distMaskImg;
// distImg 得到的是 0- 1之间的数,转化成8位单通道的。
distImg.convertTo(distMaskImg, CV_8U);
vector<vector<Point>>contours;
//找到 marker 的轮廓
findContours(distMaskImg, contours, RETR_EXTERNAL,
CHAIN_APPROX_SIMPLE, Point(0, 0));
//create marker 填充 marker
Mat markersImg = Mat::zeros(srcImg.size(), CV_32SC1);
for (int i = 0; i < contours.size(