3.3.4 距离变换-扫描
1 //////https://blog.csdn.net/gone_huilin/article/details/53223026 2 #include <opencv2/imgproc/imgproc.hpp> 3 #include <opencv2/core/core.hpp> 4 #include <opencv2/highgui/highgui.hpp> 5 #include <iostream> 6 // 计算欧式距离 7 float calcEuclideanDistance(int x1, int y1, int x2, int y2) 8 { 9 return sqrt(float((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2))); 10 } 11 // 计算棋盘距离 12 int calcChessboardDistance(int x1, int y1, int x2, int y2) 13 { 14 return cv::max(abs(x1 - x2), abs(y1 - y2)); 15 } 16 // 计算街区距离 17 int calcBlockDistance(int x1, int y1, int x2, int y2) 18 { 19 return abs(x1 - x2) + abs(y1 - y2); 20 } 21 // 距离变换函数实现 22 void distanceTrans(cv::Mat &srcImage, cv::Mat &resultIamge) 23 { 24 CV_Assert(srcImage.data != NULL); 25 cv::Mat srcGray, srcBinary; 26 // 转换成灰度图像 27 cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY); 28 // 转换成二值图像 29 threshold(srcGray, srcBinary, 100, 255, cv::THRESH_BINARY); 30 cv::imshow("srcBinary", srcBinary); 31 int rows = srcBinary.rows; 32 int cols = srcBinary.cols; 33 uchar* pDataOne; 34 uchar* pDataTwo; 35 float disPara = 0; 36 float fDisMin = 0; 37 // 第一遍遍历图像用左模板更新像素值 38 for (int i = 1; i < rows - 1; i++) 39 { 40 // 图像指针获取 41 pDataOne = srcBinary.ptr<uchar>(i); 42 for (int j = 1; j < cols; j++) 43 { 44 // 分别计算其左模板掩码相关距离 45 // pL pL 46 // pL p 47 // pL 48 pDataTwo = srcBinary.ptr<uchar>(i - 1); 49 disPara = calcEuclideanDistance(i, j, i - 1, j - 1); 50 fDisMin = cv::min((float)pDataOne[j], 51 disPara + pDataTwo[j - 1]); 52 disPara = calcEuclideanDistance(i, j, i - 1, j); 53 fDisMin = cv::min(fDisMin, 54 disPara + pDataTwo[j]); 55 pDataTwo = srcBinary.ptr<uchar>(i); 56 disPara = calcEuclideanDistance(i, j, i, j - 1); 57 fDisMin = cv::min(fDisMin, 58 disPara + pDataTwo[j - 1]); 59 pDataTwo = srcBinary.ptr<uchar>(i + 1); 60 disPara = calcEuclideanDistance(i, j, i + 1, j - 1); 61 fDisMin = cv::min(fDisMin, 62 disPara + pDataTwo[j - 1]); 63 pDataOne[j] = (uchar)cvRound(fDisMin); 64 } 65 } 66 // 第二遍遍历图像用右模板更新像素值 67 for (int i = rows - 2; i > 0; i--) 68 { 69 pDataOne = srcBinary.ptr<uchar>(i); 70 for (int j = cols - 1; j >= 0; j--) 71 { 72 // 分别计算其右模板掩码相关距离 73 // pR pR 74 // pR p 75 // pR 76 pDataTwo = srcBinary.ptr<uchar>(i + 1); 77 disPara = calcEuclideanDistance(i, j, i + 1, j); 78 fDisMin = cv::min((float)pDataOne[j], 79 disPara + pDataTwo[j]); 80 disPara = calcEuclideanDistance(i, j, i + 1, j + 1); 81 fDisMin = cv::min(fDisMin, 82 disPara + pDataTwo[j + 1]); 83 pDataTwo = srcBinary.ptr<uchar>(i); 84 disPara = calcEuclideanDistance(i, j, i, j + 1); 85 fDisMin = cv::min(fDisMin, 86 disPara + pDataTwo[j + 1]); 87 pDataTwo = srcBinary.ptr<uchar>(i - 1); 88 disPara = calcEuclideanDistance(i, j, i - 1, j + 1); 89 fDisMin = cv::min(fDisMin, 90 disPara + pDataTwo[j + 1]); 91 pDataOne[j] = (uchar)cvRound(fDisMin); 92 } 93 } 94 resultIamge = srcBinary.clone(); 95 } 96 int main() 97 { 98 cv::Mat srcImage = cv::imread("D:\\沙漠.jpg"); 99 if (!srcImage.data) 100 return -1; 101 cv::Mat resultIamge; 102 distanceTrans(srcImage, resultIamge); 103 cv::imshow("resultIamge", resultIamge); 104 cv::waitKey(0); 105 return 0; 106 }