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 }