OpenCV3.2图像分割 实例6:基于距离变换的分水岭粘连对象分离与计数

发布时间 2023-08-18 09:05:23作者: 一杯清酒邀明月
 1 #include <opencv2/opencv.hpp>
 2 #include <iostream>
 3  
 4 using namespace cv;
 5 using namespace std;
 6  
 7 int main(int argc, char** argv) {
 8     Mat src = imread("pill_002.png");//pill_002.png  coins_001.jpg
 9     if (src.empty()) {
10         printf("could not load image...\n");
11         return -1;
12     }
13     namedWindow("input image", CV_WINDOW_AUTOSIZE);
14     imshow("input image", src);
15  
16     Mat gray, binary, shifted;
17     //边缘保留(空间、颜色差值<21、51) 减少差异化
18     pyrMeanShiftFiltering(src, shifted, 21, 51);
19     imshow("shifted", shifted);
20  
21     cvtColor(shifted, gray, COLOR_BGR2GRAY);//转换为灰度图像
22     //灰度图像进行二值化
23     threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
24     imshow("binary", binary);
25  
26     // distance transform 距离变化
27     Mat dist;
28     distanceTransform(binary, dist, DistanceTypes::DIST_L2, 3, CV_32F);//使用3*3进行
29     normalize(dist, dist, 0, 1, NORM_MINMAX);
30     imshow("distance result", dist);
31  
32     // binary
33     threshold(dist, dist, 0.4, 1, THRESH_BINARY);
34     imshow("distance binary", dist);
35  
36     // markers 找到山峰的旗子
37     Mat dist_m;
38     dist.convertTo(dist_m, CV_8U);
39     vector<vector<Point>> contours;
40     //寻找轮廓contours
41     findContours(dist_m, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
42  
43     // create markers 填充轮廓
44     Mat markers = Mat::zeros(src.size(), CV_32SC1);
45     for (size_t t = 0; t < contours.size(); t++) {
46         drawContours(markers, contours, static_cast<int>(t), Scalar::all(static_cast<int>(t) + 1), -1);
47     }
48     //左上角显示一个圆(可有可无)
49     circle(markers, Point(5, 5), 3, Scalar(255), -1);
50     //markers放大10000倍进行显示
51     imshow("markers", markers*10000);
52  
53     // 形态学操作 - 彩色图像也可以,目的是去掉干扰,让结果更好
54     Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
55     morphologyEx(src, src, MORPH_ERODE, k);
56  
57     // 完成分水岭变换
58     watershed(src, markers);
59     Mat mark = Mat::zeros(markers.size(), CV_8UC1);
60     markers.convertTo(mark, CV_8UC1);
61     bitwise_not(mark, mark, Mat());
62     //imshow("watershed result", mark);//中间是白色线进行分割
63  
64     // generate random color 生成随机颜色
65     vector<Vec3b> colors;
66     for (size_t i = 0; i < contours.size(); i++) {
67         int r = theRNG().uniform(0, 255);
68         int g = theRNG().uniform(0, 255);
69         int b = theRNG().uniform(0, 255);
70         colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
71     }
72  
73     // 颜色填充与最终显示
74     Mat dst = Mat::zeros(markers.size(), CV_8UC3);
75     int index = 0;
76     for (int row = 0; row < markers.rows; row++) {
77         for (int col = 0; col < markers.cols; col++) {
78             index = markers.at<int>(row, col);
79             if (index > 0 && index <= contours.size()) {
80                 dst.at<Vec3b>(row, col) = colors[index - 1];
81             } else {
82                 dst.at<Vec3b>(row, col) = Vec3b(0, 0, 0);
83             }
84         }
85     }
86  
87     imshow("Final Result", dst);
88     printf("number of objects : %d\n", contours.size());
89  
90     waitKey(0);
91     return 0;
92 }