C++: void distanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize)
参数详解:
InputArray src:输入的图像,一般为二值图像
OutputArray dst:输出的图像
int distanceType:所用的求解距离的类型、
It can be CV_DIST_L1, CV_DIST_L2 , or CV_DIST_C
mask_size 距离变换掩模的大小,可以是 3 或 5. 对 CV_DIST_L1 或 CV_DIST_C 的情况,参数值被强制设定为 3, 因为 3×3 mask 给出 5×5 mask 一样的结果,而且速度还更快。
- mask
- 用户自定义距离情况下的 mask。 在 3×3 mask 下它由两个数(水平/垂直位量,对角线位移量)组成, 5×5 mask 下由三个数组成(水平/垂直位移量,对角位移和 国际象棋里的马步(马走日))
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 Mat src; 8 9 int main(int argc, char** argv) 10 { 11 src = imread("分水岭.jpg"); 12 if (src.empty()) 13 { 14 printf("Can not load Image..."); 15 return -1; 16 } 17 imshow("input Image",src); 18 19 //白色背景变成黑色 20 for (int row=0;row<src.rows;row++) 21 { 22 for (int col = 0; col < src.cols; col++) { 23 if (src.at<Vec3b>(row, col) == Vec3b(255, 255, 255)) { 24 src.at<Vec3b>(row, col)[0] = 0; 25 src.at<Vec3b>(row, col)[1] = 0; 26 src.at<Vec3b>(row, col)[2] = 0; 27 } 28 } 29 } 30 imshow("black backgroung", src); 31 32 //sharpen(提高对比度) 33 Mat kernel = (Mat_<float>(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1); 34 35 //make it more sharp 36 Mat imgLaplance; 37 Mat sharpenImg = src; 38 //拉普拉斯算子实现边缘提取 39 filter2D(src, imgLaplance, CV_32F, kernel, Point(-1, -1), 0, BORDER_DEFAULT);//拉普拉斯有浮点数计算,位数要提高到32 40 src.convertTo(sharpenImg, CV_32F); 41 42 //原图减边缘(白色)实现边缘增强 43 Mat resultImg = sharpenImg - imgLaplance; 44 45 resultImg.convertTo(resultImg,CV_8UC3); 46 imgLaplance.convertTo(imgLaplance, CV_8UC3); 47 imshow("sharpen Image", resultImg); 48 49 //转换成二值图 50 Mat binary; 51 cvtColor(resultImg, resultImg, CV_BGR2GRAY); 52 threshold(resultImg, binary,40,255,THRESH_BINARY|THRESH_OTSU); 53 imshow("binary image",binary); 54 55 //距离变换 56 Mat distImg; 57 distanceTransform(binary,distImg,DIST_L1,3,5); 58 normalize(distImg, distImg, 0, 1, NORM_MINMAX); 59 imshow("dist image",distImg); 60 61 //二值化 62 threshold(distImg, distImg, 0.4, 1, THRESH_BINARY); 63 imshow("dist binary image", distImg); 64 65 //腐蚀(使得连在一起的部分分开) 66 Mat k1 = Mat::ones(3, 3, CV_8UC1); 67 erode(distImg, distImg, k1); 68 imshow("分开", distImg); 69 70 //标记 71 Mat dist_8u; 72 distImg.convertTo(dist_8u,CV_8U); 73 vector<vector<Point>> contours; 74 findContours(dist_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); 75 76 //创建标记 77 Mat marker = Mat::zeros(src.size(),CV_32SC1); 78 79 //画标记 80 for (size_t i = 0; i < contours.size(); i++) 81 { 82 drawContours(marker,contours,static_cast<int>(i),Scalar(static_cast<int>(i)+1),-1); 83 } 84 85 circle(marker, Point(5, 5), 3, Scalar(255, 255, 255), -1); 86 imshow("marker",marker*1000); 87 88 //分水岭变换 89 watershed(src,marker);//根据距离变换的标记,在原图上分离 90 Mat water = Mat::zeros(marker.size(),CV_8UC1); 91 marker.convertTo(water,CV_8UC1); 92 bitwise_not(water, water,Mat());//取反操作 93 //imshow("源 image", src); 94 imshow("watershed Image", water); 95 96 // generate random color 97 vector<Vec3b> colors; 98 for (size_t i = 0; i < contours.size(); i++) { 99 int r = theRNG().uniform(0, 255); 100 int g = theRNG().uniform(0, 255); 101 int b = theRNG().uniform(0, 255); 102 colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r)); 103 } 104 105 // fill with color and display final result 106 Mat dst = Mat::zeros(marker.size(), CV_8UC3); 107 for (int row = 0; row < marker.rows; row++) { 108 for (int col = 0; col < marker.cols; col++) { 109 int index = marker.at<int>(row, col); 110 if (index > 0 && index <= static_cast<int>(contours.size())) { 111 dst.at<Vec3b>(row, col) = colors[index - 1]; 112 } 113 else { 114 dst.at<Vec3b>(row, col) = Vec3b(0, 0, 0); 115 } 116 } 117 } 118 imshow("Final Result", dst); 119 waitKey(0); 120 return 0; 121 }