目前正在学习<图像处理,分析与机器视觉>里面有提到距离变换计算,以此笔记记录生活。 
距离变换的定义 :计算图像中像素点到最近零像素点的距离,也就是零像素点的最短距离。

Mat srcImage = imread("/Users/hanoi/Desktop/hand.jpg",0);
Mat dist_image(size,CV_32FC1);
distanceTransform(srcImage, dist_image, CV_DIST_L2, CV_DIST_MASK_3);
  • 1
  • 2
  • 3
int main(int argc, const char * argv[])
{Mat srcImage = imread("/Users/hanoi/Desktop/hand.jpg",0);printf("step=%ld\n",srcImage.step[0]);if (!srcImage.data){cout << "读入图片错误!" << endl;system("pause");return -1;}Size size;size.width =  srcImage.cols;size.height = srcImage.rows;Mat dist_image(size,CV_32FC1);Mat bi_src(size,CV_8SC1);distanceTransform(srcImage, dist_image, CV_DIST_L2, CV_DIST_MASK_3);normalize(dist_image, dist_image, 0, 1, NORM_MINMAX);imshow("src",dist_image);//imwrite("/Users/hanoi/Desktop/gray1.jpg", dist_image );Mat myImage(size,CV_8UC1);for (int j=0; j<dist_image.rows; j++){for (int i=0; i<dist_image.cols; i++){double m = dist_image.at<float>(j,i );int y = m * 255;if(y > 255){y = 255;}*(myImage.data + j*myImage.step[0] + i) = y;}}imwrite("/Users/hanoi/Desktop/gray1.bmp", myImage);waitKey();return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

我们的type是CV_32FC1,所以每个像素是4个字节,为了能保存图像,在进行归一化处理之后,需要用距离*255,然后作为该像素点的亮度值。

distanceTransform是opencv的提供的计算距离转换的函数,个人觉得要主要是dest的输出,存的是距离的矩阵,所以这里我们创建的时候type是CV_32FC1。 
其中距离的计算方法: 

为了减少计算了量,我们采用的是一种倒角模版的算法,只需要对图像进行两次扫描玖可以实现距离变换,该方法被称为chamfer倒角距离变换,该模版如下: 

网络代码参考:

//距离变换的扫描实现  #include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>  using namespace cv;
using namespace std;  //计算欧氏距离的函数
float calcEuclideanDiatance(int x1, int y1, int x2, int y2)
{  return sqrt(float((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)));
}  //计算棋盘距离的函数
int calcChessboardDistance(int x1, int y1, int x2, int y2)
{  return cv::max(abs(x1 - x2), (y1 - y2));
}  //计算麦哈顿距离(街区距离)
int calcBlockDistance(int x1, int y1, int x2, int y2)
{  return abs(x1 - x2) + abs(y1 - y2);
}  //距离变换函数的实现
void distanceTrans(Mat &srcImage, Mat &dstImage)
{  CV_Assert(srcImage.data != nullptr);      //CV_Assert()若括号中的表达式值为false,则返回一个错误信息。  //定义灰度图像的二值图像  Mat grayImage, binaryImage;  //将原图像转换为灰度图像  cvtColor(srcImage, grayImage, CV_BGR2GRAY);  //将灰度图像转换为二值图像  threshold(grayImage, binaryImage, 100, 255, THRESH_BINARY);  imshow("二值化图像", binaryImage);  int rows = binaryImage.rows;  int cols = binaryImage.cols;  uchar *pDataOne;  uchar *pDataTwo;  float disPara = 0;  float fDisMIn = 0;  //第一遍遍历图像,使用左模板更新像素值  for (int i = 1; i < rows - 1; i++)  {  //图像的行指针的获取  pDataOne = binaryImage.ptr<uchar>(i);  for (int j = 1; j < cols; j++)  {  //分别计算左模板掩码的相关距离  //PL  PL  //PL  P  //PL  pDataTwo = binaryImage.ptr<uchar>(i - 1);  disPara = calcEuclideanDiatance(i, j, i - 1, j - 1);  fDisMIn = cv::min((float)pDataOne[j], disPara + pDataTwo[j - 1]);  disPara = calcEuclideanDiatance(i, j, i - 1, j);  fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j]);  pDataTwo = binaryImage.ptr<uchar>(i);  disPara = calcEuclideanDiatance(i, j, i, j - 1);  fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j-1]);  pDataTwo = binaryImage.ptr<uchar>(i+1);  disPara = calcEuclideanDiatance(i, j, i+1,j-1);  fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j - 1]);  pDataOne[j] = (uchar)cvRound(fDisMIn);  }  }  //第二遍遍历图像,使用右模板更新像素值  for (int i = rows - 2; i > 0; i--)  {  pDataOne = binaryImage.ptr<uchar>(i);  for (int j = cols - 1; j >= 0; j--)  {  //分别计算右模板掩码的相关距离  //pR  pR  //pR  p  //pR  pDataTwo = binaryImage.ptr<uchar>(i + 1);  disPara = calcEuclideanDiatance(i, j, i + 1, j);  fDisMIn = cv::min((float)pDataOne[j], disPara + pDataTwo[j]);  disPara = calcEuclideanDiatance(i, j, i + 1, j + 1);  fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j+1]);  pDataTwo = binaryImage.ptr<uchar>(i);  disPara = calcEuclideanDiatance(i, j, i, j +1);  fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j + 1]);  pDataTwo = binaryImage.ptr<uchar>(i - 1);  disPara = calcEuclideanDiatance(i, j, i - 1, j + 1);  fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j + 1]);  pDataOne[j] = (uchar)cvRound(fDisMIn);  }  }  dstImage = binaryImage.clone();
}  //主函数
int main()
{  Mat srcImage = imread("2345.jpg");  if (!srcImage.data)  {  cout << "读入图片错误!" << endl;  system("pause");  return -1;  }  Mat dstImage;  distanceTrans(srcImage, dstImage);  imshow("距离变换图像", dstImage);  waitKey();  return 0;
}  

OpenCV 距离变换的笔记相关推荐

  1. OpenCV距离变换和分水岭算法的图像分割

    OpenCV距离变换和分水岭算法的图像分割 距离变换和分水岭算法的图像分割 目标 代码 说明/结果 距离变换和分水岭算法的图像分割 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: f ...

  2. OpenCV(26)图像分割 -- 距离变换与分水岭算法(硬币检测、扑克牌检测、车道检测)

    目录 一.基础理论 1.思想 2.原理 二.分水岭实战:硬币 步骤归纳 1.把原图像转二值图 2.开运算去噪 3.确定背景区域(膨胀)(得到背景/最大连通域) 4.确定前景区域(距离变换) (分离)( ...

  3. 【OpenCV 4开发详解】图像距离变换

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  4. 图像识别中距离变换的原理及作用详解,并附用OpenCV中的distanceTransform实现距离变换的代码

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 距离变换的定义是计算一个图像中非零像素点到最近的 ...

  5. OpenCV使用Laplacian filtering和距离变换以及Laplacian滤波对重叠对象进行分段的实例(附完整代码)

    OpenCV使用Laplacian filtering和距离变换以及Laplacian滤波对重叠对象进行分段的实例 OpenCV使用Laplacian filtering和距离变换以及Laplacia ...

  6. 【OpenCV】数字图像的距离变换算法

    数字图像的距离变换算法 图像数字化 距离 距离变换 OpenCV代码实现 C++ Python 参考博客 图像数字化 通过传感器获得的图像是平面坐标(x,y)的连续函数f(x,y),它的值图像对应位置 ...

  7. OpenCV之Python学习笔记

    RSS订阅 登陆 注册 原文链接地址:http://www.itozi.net/19477.html OpenCV之Python学习笔记 ITOZI 发布于 2015-08-06 分类:OpenSta ...

  8. 12月19日 OpenCV 实战基础学习笔记——特征匹配

    文章目录 前言 一.特征匹配 1.Brute-force 蛮力匹配 2.1 对 1 匹配 3.k 对最佳匹配 二.答题卡识别 前言 本文为12月19日 OpenCV 实战基础学习笔记--特征匹配,分为 ...

  9. 【图像处理】灰度加权距离变换(GWDT)

    [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 前言 距离变换(distance transform,DT)在图像处理.计算机视觉等领域有非 ...

最新文章

  1. 空间点像素索引(一)
  2. PHP + Redis 实现消息队列
  3. 阿里妈妈:基于动态背包的多场景广告序列投放算法
  4. Dynamips和Vmware完成CCVP试验(5)
  5. jquery form 的beforeSubmit提交前的回调函数
  6. DL之R-CNN:R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  7. 回港二次上市,会是内容社区平台的更优选吗?
  8. Java进阶:Semaphore信号量基本使用
  9. 港媒:AI技术有望助力中国核潜艇升级
  10. 又砸又烧,还要泼脏水,这谣言到底什么时候才没人信?发生这样的事真没想到.........
  11. java seteditable,Java TextField.setEditable方法代碼示例
  12. 素材 | 3D立体设定数据多彩数据统计图元素PSD模板
  13. 摩拜前端周刊第10期
  14. 《iOS8 Swift编程指南》类书图像
  15. 初步了解CUDA(零)
  16. 拓端tecdat|matlab使用Copula仿真优化市场风险
  17. VFP全面控制EXCEL
  18. HDU1269-迷宫城堡
  19. java 释放锁_Java并发编程:锁的释放
  20. 应届生小白转行新媒体运营,3个月里我都经历了什么?

热门文章

  1. BOOST_PP_CHECK_EMPTY宏相关的测试程序
  2. boost::polygon模块voronoi相关的测试程序
  3. boost::mpl模块实现insert_range相关的测试程序
  4. boost::hana::comparing用法的测试程序
  5. boost::fusion::insert_range用法的测试程序
  6. VTK:图片之ImageToStructuredPoints
  7. C语言实现升序优先队列Ascending priority queue(附完整源码)
  8. 经典C语言程序100例之九零
  9. 用python做加法_Python不用加减乘除做加法
  10. 创建android程序时 默认使用布局是,《Android移动应用基础教程》中国铁道出版社课后习题(附答案)...