码迷,mamicode.com
首页 > 其他好文 > 详细

3.3 距离变换

时间:2018-08-16 00:59:41      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:one   sse   article   gif   read   jpg   inux   roc   技术   

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 }
View Code

应用:

https://blog.csdn.net/dan1900/article/details/16989023

https://blog.csdn.net/augusdi/article/details/9022077

https://blog.csdn.net/u014751607/article/details/61919706

https://blog.csdn.net/qq_34784753/article/details/68951918?locationNum=8&fps=1

https://blog.csdn.net/guoruijiushiwo/article/details/72841482

 

3.3.5 距离变换-distanceTransform

Opencv中distanceTransform方法用于计算图像中每一个非零点距离离自己最近的零点的距离,distanceTransform的第二个Mat矩阵参数dst保存了每一个点与最近的零点的距离信息,图像上越亮的点,代表了离零点的距离越远。

技术分享图片
 1 ////////https://blog.csdn.net/gone_huilin/article/details/53223066
 2 #include <opencv2/imgproc/imgproc.hpp>  
 3 #include <opencv2/core/core.hpp>        
 4 #include <opencv2/highgui/highgui.hpp> 
 5 #include <iostream> 
 6 int main()
 7 {
 8     cv::Mat srcImage = cv::imread("D:\\六角星.jpg");
 9     if (!srcImage.data)
10         return -1;
11     // 转换为灰度图像
12     cv::Mat srcGray;
13     cvtColor(srcImage, srcGray, CV_BGR2GRAY);
14     // 转换为二值图像
15     cv::Mat srcBinary;
16     threshold(srcGray, srcBinary, 160, 255, cv::THRESH_BINARY);
17     // 距离变换
18     cv::Mat dstImage;
19     cv::distanceTransform(srcBinary, dstImage, CV_DIST_L2,
20         CV_DIST_MASK_PRECISE);
21     // 归一化矩阵
22     cv::normalize(dstImage, dstImage, 0, 1., cv::NORM_MINMAX);
23     cv::imshow("srcBinary", srcBinary);
24     cv::imshow("dstImage", dstImage);
25     cv::waitKey(0);
26     return 0;
27 }
View Code

技术分享图片

技术分享图片技术分享图片

 

技术分享图片
 1 #include "core/core.hpp"
 2 #include "imgproc/imgproc.hpp"
 3 #include "highgui/highgui.hpp"
 4 
 5 using namespace cv;
 6 
 7 int main(int argc, char *argv[])
 8 {
 9     float maxValue = 0;  //定义距离变换矩阵中的最大值
10     //Mat image = imread(argv[1]);
11     Mat image = imread("D:\\字母ABCD.jpg");
12     Mat imageGray;
13     cvtColor(image, imageGray, CV_RGB2GRAY);
14     imageGray = ~imageGray;  //取反
15     GaussianBlur(imageGray, imageGray, Size(5, 5), 2); //滤波
16     threshold(imageGray, imageGray, 20, 200, CV_THRESH_BINARY); //阈值
17     imshow("s", imageGray);
18     Mat imageThin(imageGray.size(), CV_32FC1); //定义保存距离变换结果的Mat矩阵
19     distanceTransform(imageGray, imageThin, CV_DIST_L2, 3);  //距离变换
20     Mat distShow;
21     distShow = Mat::zeros(imageGray.size(), CV_8UC1); //定义细化后的字符轮廓
22     for (int i = 0; i<imageThin.rows; i++)
23     {
24         for (int j = 0; j<imageThin.cols; j++)
25         {
26             if (imageThin.at<float>(i, j)>maxValue)
27             {
28                 maxValue = imageThin.at<float>(i, j);  //获取距离变换的极大值
29             }
30         }
31     }
32     for (int i = 0; i<imageThin.rows; i++)
33     {
34         for (int j = 0; j<imageThin.cols; j++)
35         {
36             if (imageThin.at<float>(i, j)>maxValue / 1.9)
37             {
38                 distShow.at<uchar>(i, j) = 255;   //符合距离大于最大值一定比例条件的点设为255
39             }
40         }
41     }
42     imshow("Source Image", image);
43     imshow("Thin Image", distShow);
44     waitKey();
45     return 0;
46 }
View Code

技术分享图片

技术分享图片

技术分享图片

 

技术分享图片
 1 ////////distanceTransform应用:查找物体质心
 2 ////////https://blog.csdn.net/dcrmg/article/details/52517991
 3 #include "core/core.hpp"
 4 #include "imgproc/imgproc.hpp"
 5 #include "highgui/highgui.hpp"
 6 
 7 using namespace cv;
 8 
 9 int main(int argc, char *argv[])
10 {
11     float maxValue = 0;  //定义距离变换矩阵中的最大值
12     Point Pt(0, 0);
13     Mat image = imread("D:\\六角星.jpg");
14     Mat imageGray;
15     cvtColor(image, imageGray, CV_RGB2GRAY);
16     imageGray = ~imageGray;  //取反
17     GaussianBlur(imageGray, imageGray, Size(5, 5), 2); //滤波
18     threshold(imageGray, imageGray, 20, 200, CV_THRESH_BINARY); //阈值化    
19     Mat imageThin(imageGray.size(), CV_32FC1); //定义保存距离变换结果的Mat矩阵
20     distanceTransform(imageGray, imageThin, CV_DIST_L2, 3);  //距离变换
21     Mat distShow;
22     distShow = Mat::zeros(imageGray.size(), CV_8UC1); //定义细化后的字符轮廓
23     for (int i = 0; i<imageThin.rows; i++)
24     {
25         for (int j = 0; j<imageThin.cols; j++)
26         {
27             distShow.at<uchar>(i, j) = imageThin.at<float>(i, j);
28             if (imageThin.at<float>(i, j)>maxValue)
29             {
30                 maxValue = imageThin.at<float>(i, j);  //获取距离变换的极大值
31                 Pt = Point(j, i);  //坐标
32             }
33         }
34     }
35     normalize(distShow, distShow, 0, 255, CV_MINMAX); //为了显示清晰,做了0~255归一化
36     circle(image, Pt, maxValue, Scalar(0, 0, 255), 3);
37     circle(image, Pt, 3, Scalar(0, 255, 0), 3);
38     imshow("Source Image", image);
39     imshow("Thin Image", distShow);
40     waitKey();
41     return 0;
42 }
View Code

技术分享图片

技术分享图片

技术分享图片
 1 ////////https://blog.csdn.net/wuhaibing_cver/article/details/8602461
 2 #include <opencv2/imgproc/imgproc.hpp>  
 3 #include <opencv2/core/core.hpp>        
 4 #include <opencv2/highgui/highgui.hpp> 
 5 #include <cv.h>
 6 #include <highgui.h>
 7 
 8 int main()
 9 {
10     char* filename = "D:\\二值化手.jpg";
11     IplImage* src_image = cvLoadImage(filename, 1);
12     if (!src_image)
13         return -1;
14     cvNamedWindow("src");
15 
16     CvSize size = cvGetSize(src_image);
17     IplImage* gray_image = cvCreateImage(size, 8, 1);
18     cvCvtColor(src_image, gray_image, CV_BGR2GRAY);
19 
20     IplImage* dist_image = cvCreateImage(size, 32, 1);
21     IplImage* bi_src = cvCreateImage(size, 8, 1);
22     IplImage* dist8u_image = cvCreateImage(size, 8, 1);
23     IplImage* bi_dist = cvCreateImage(size, 8, 1);
24     //原图像二值化
25     cvThreshold(gray_image, bi_src, 100, 255, CV_THRESH_BINARY);
26     //距离变换
27     cvDistTransform(bi_src, dist_image, CV_DIST_L2, 3, 0, 0);
28     //找最大值
29     double max;
30     cvMinMaxLoc(dist_image, 0, &max, 0, 0);
31     cvCvtScale(dist_image, dist8u_image, 255. / max);
32     //对距离图像二值化,去除手指部分
33     cvThreshold(dist8u_image, bi_dist, 80, 255, CV_THRESH_BINARY);
34     //求重心
35     float s = 0.0, x = 0.0, y = 0.0;
36     uchar* data = (uchar*)bi_dist->imageData;
37     int step = bi_dist->widthStep;
38     for (int h = 0; h<bi_dist->height; h++)
39         for (int w = 0; w<bi_dist->width; w++)
40             if (255 == data[step*h + w])
41             {
42                 x += w;
43                 y += h;
44                 s++;
45             }
46     if (s>0)
47     {
48         x = x / s;
49         y = y / s;
50     }
51     CvPoint pos = cvPoint((int)x, (int)y);
52 
53     cvCircle(src_image, pos, 3, CV_RGB(255, 0, 0), 1, CV_AA);
54     cvShowImage("src", src_image);
55     cvWaitKey(-1);
56 
57     cvDestroyWindow("src");
58     cvReleaseImage(&src_image);
59     cvReleaseImage(&gray_image);
60     cvReleaseImage(&bi_src);
61     cvReleaseImage(&dist8u_image);
62     cvReleaseImage(&bi_dist);
63 
64     return 0;
65 }
View Code

技术分享图片

参考:

https://blog.csdn.net/dcrmg/article/details/52517991

https://blog.csdn.net/wuhaibing_cver/article/details/8602461

原理参考:https://blog.csdn.net/liubing8609/article/details/78483667

其他参考:

https://blog.csdn.net/abcjennifer/article/details/7617883

https://blog.csdn.net/haoji007/article/details/52063389

http://www.linuxkiss.com/287.html

 

3.3 距离变换

标签:one   sse   article   gif   read   jpg   inux   roc   技术   

原文地址:https://www.cnblogs.com/thebreakofdawn/p/9484458.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!