数字图像的距离变换算法

  • 图像数字化
  • 距离
  • 距离变换
  • OpenCV代码实现
    • C++
    • Python
  • 参考博客

图像数字化

通过传感器获得的图像是平面坐标(x,y)的连续函数f(x,y),它的值图像对应位置的亮度。为了能够让计算机来处理,需要对图像进行采样,并且对亮度值进行量化。

  1. 采样。对连续函数f(x,y)进行采样,就是分别对x轴和y轴,按照固定间隔取值,得到平面坐标上的M×N个点,将其函数值作为元素生成M行N列的矩阵;
  2. 量化亮度值。将f(x,y)的值转化为等价的整数值的过程称为量化,量化的级别越高,图像越细致。通常将亮度值表示为0-255之间的整数。

这样,在计算机中通常以矩阵表示数字图像,矩阵的元素对应图像的亮度信息。

距离

满足以下三个条件的函数D称作距离:

  1. 同一性:
  2. 对称性:
  3. 三角不等式:

数字图像的距离有多种定义方式,包括欧式距离、城市街区距离、棋盘距离等。以下以两坐标点a=(i,j)a=(i,j)a=(i,j)和b=(k,l)b=(k,l)b=(k,l)的距离为例,来说明各种距离的定义方式。

欧式距离DE就是通常所说的距离,它定义为:

欧式距离在事实上比较直观,但是平方根计算比较费时,且距离可能不是数。

城市街区距离D4,它定义为在只允许横向和纵向运动的情况下,从起点到终点的移动步数。用公式表示为:

符号D4中的4表示在这种定义下,像素点是4邻接的,即每个点只与它的上、下、左、右相邻的4个点之间的距离为1。

如果允许横向、纵向和沿对角线方向移动,则可以得到棋盘距离D8的定义:

符号D8中的8表示在这种定义下,像素点是8邻接的,即每个点只与它的上、下、左、右、四个对角线方向相邻的8个点之间的距离为1。

显然,以上三种距离的定义都满足距离的定义条件。

距离变换

距离变换也叫作距离函数或者斜切算法。它是距离概念的一个应用,图像处理的一些算法以距离变换为基础。距离变换描述的是图像中像素点与某个区域块的距离,区域块中的像素点值为0,临近区域块的像素点有较小的值,离它越远值越大。

以二值图像为例,其中区域块内部的像素值为1,其他像素值为0。距离变换给出每个像素点到最近的区域块边界的距离,区域块内部的距离变换结果为0。输入图像如图1所示,D4距离的距离变换结果如图2所示。


下面来讨论距离变换算法,其核心是利用两个小的局部掩膜遍历图像。第一遍利用掩模1,左上角开始,从左往右,从上往下。第二遍利用第二个掩模,右下角开始,从右往左,从下往上。掩模形状如下图所示:


按照某种距离(如:D4距离或D8距离)对大小为M×N的图像中的区域块作距离变换,算法过程如下:

  1. 建立一个大小为M×N的数组F,作如下的初始化:将区域块中的元素设置为0,其余元素设置为无穷;
  2. 利用掩模1(mask1),左上角开始,从左往右,从上往下遍历数组,将掩模中P点对应的元素的值作如下更新:
  3. 利用掩模2(mask2),右下角开始,从右往左,从下往上遍历数组,将掩模中P点对应的元素的值作如下更新:

    最终得到的更新后的数组即为距离变换的结果。

这个算法过程在图像编边界需要做出调整,因为在边界处,掩模不能全部覆盖图像,这时可以将掩模中没有对应元素的位置的值当作0来处理。

OpenCV代码实现

C++

这个算法过程经过很多的改进,但基本原理并没有区别。开源计算机视觉库OpenCV中,距离变换算法有相应的实现,声明如下:

CV_EXPORTS_W void distanceTransform( InputArray src, OutputArray dst,int distanceType, int maskSize, int dstType=CV_32F);

参数详解:

  • InputArray src:输入图像,一般为二值图像;
  • OutputArray dst:输出的图像,距离变换结果;
  • int distanceType:用于距离变换的距离类型(欧氏距离:DIST_L2 = 2;D4D_4D4​距离:DIST_L1 =
    1;D8D_8D8​距离:DIST_C = 3等);
  • int mask_size:距离变换掩模的大小,一般为3或5; int
  • dstType:输出图像的数据类型,可以为CV_8U或CV_32F。

下面我们用一个具体的例子来展示距离变换的效果。将大小为480*480,其中有三个像素点设置为1,其余都为0的一张图片作为输入图像,分别在欧式距离、D4D_4D4​距离和D8D_8D8​距离下,距离变换的结果。

效果如下图所示:



下面是代码实现:

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;int main()
{//初始化输入图像和变换结果图像Mat mat(480, 480, CV_8UC1, Scalar(0)), transMatE, transMatD4, transMatD8;//给输入图像指定三个像素点作为距离变换原点(区域块)mat.at<uchar>(100, 200) = 1;mat.at<uchar>(200, 100) = 1;mat.at<uchar>(300, 300) = 1;//将将输入图像中1和0调换,使得原点距离为0mat = 1 - mat;//显示原始图像(显示为黑色)imshow("原始图片", mat);//分别利用欧式距离、D4距离和D8距离作距离变换,将结果存入transMatD4、transMatD8和transMatEdistanceTransform(mat, transMatE, DIST_L2, 0);distanceTransform(mat, transMatD4, DIST_L1, 0, CV_8U);distanceTransform(mat, transMatD8, DIST_C, 0);//欧式距离与D8距离作变换后,值为32位浮点数,以下代码将其值转为uchar类型transMatE.convertTo(transMatE, CV_8U);transMatD8.convertTo(transMatD8, CV_8U);//显示距离变换结果imshow("欧式距离变换后的图片", transMatE);imshow("D4距离变换后的图片", transMatD4);imshow("D8距离变换后的图片", transMatD8);waitKey();return 0;
}

Python

距离变换函数用于计算每个像素离最近0值像素的距离,输入是一个二值图像。图像上越亮的点,代表了离零点的距离越远。距离变换应用于图像细化,图像分割等。

dist_img = cv2.distanceTransform(img_bin, distance_type, mask_size)
# distance_type 计算距离的公式
#     参看 cv2.DIST_* ,常用cv2.DIST_L1
# mask_size
#     参看 cv2.DIST_MASK_*

import cv2
from cvutils import utils
from matplotlib import pyplot as pltimg = cv2.imread('laugh.jpg', 0)
img_filtered = cv2.bilateralFilter(img, 21, 75, 75)
img_bin = utils.convert2binary(img_filtered, ksize=91)dist_img = cv2.distanceTransform(img_bin, cv2.DIST_L1, cv2.DIST_MASK_3)plt.subplot(1, 2, 1), plt.imshow(dist_img)
plt.title("jet dist"), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(cv2.equalizeHist(cv2.convertScaleAbs(dist_img)), cmap='gray')
plt.title("gray_dist"), plt.xticks([]), plt.yticks([])
plt.show()

参考博客

数字图像的距离变换算法
OpenCV-Python距离变换函数

【OpenCV】数字图像的距离变换算法相关推荐

  1. 数字图像的距离变换算法

    数字图像的距离变换算法 一.图像数字化 二.距离 三.距离变换 四.OpenCV代码实现 一.图像数字化 通过传感器获得的图像是平面坐标(x,y)的连续函数f(x,y),它的值图像对应位置的亮度.为了 ...

  2. 【图像处理】——距离变换算法

    前言 通过本文可以了解到 什么是图像的距离? 什么是距离变换 距离变换的计算 OpenCV中距离变换的实现 什么是图像的距离? 距离(distance)是描述图像两点像素之间的远近关系的度量,常见的度 ...

  3. cv::cuda与CUDA的NPP库、距离变换和分水岭并行版本尝试

    因为不想什么函数都自己写设备核函数,看到opencv有对应的cuda版本的函数比如滤波,然而CUDA的NPP库也提供了对应的滤波函数,我不知道哪个性能更高(当然肯定要比纯CPU版本快,但我没测试过) ...

  4. 二值图像的距离变换研究

    http://blog.csdn.net/trent1985/article/details/18081761 [研究内容] 二值图像距离变换 [正文] 二值图像距离变换的概念由Rosenfeld和P ...

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

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

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

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

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

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

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

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

  9. OpenCV 距离变换的笔记

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

最新文章

  1. 【Java学习笔记之十】Java中循环语句foreach使用总结及foreach写法失效的问题
  2. Leaflet中使用Leaflet.Spin插件实现地图加载等待效果
  3. javaScript的使用(5)DOM事件
  4. 头条上python广告_满大街都是Python广告,真的如广告说的那样方便吗?,学精通后真能月如过万吗?业内大佬怎么看?...
  5. IBASE 不能被编辑
  6. 枚举:如何正确使用name()和toString()方法
  7. 在知乎上泡了这么久,工作、工资、生活还是没有起色是什么原因?
  8. java取模运算_Java的四则运算符与取模运算符
  9. 单片机ADC采样算法----中位值平均滤波法
  10. 小技巧 ----- 计数数组中小于 target 的元素个数
  11. 给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大
  12. 【浏览器书签】浏览器书签解析,导入
  13. canvas绘制竖排的数字_小程序利用Canvas绘制图片和竖排文字
  14. Spring(26)——PathMatchingResourcePatternResolver
  15. unity 打包APK 应用未安装
  16. 初学安装oracle11g遇到的问题,以及解决方案
  17. 日历组件(可加上一年下一年))
  18. PartnerLink,PartnerLinkType详解
  19. 【深入理解计算机系统】第三章重点汇总
  20. 序:何为高级java开发工程师?

热门文章

  1. php - 超详细将 pdf 文档格式转换为图片格式,将 offce pdf 演示文稿转成图像 png / jpg(小白一看就懂的详细教程,附带完整示例源代码)
  2. java实现微信运动数据,从小程序的获取及存储
  3. 前端必备英语单词(学习参考)
  4. 自定义Camera系列之:GLSurfaceView + Camera
  5. Prometheus监控运维实战十: 主机监控指标
  6. DISRUPT 快的原因
  7. python求最值_python怎么求一个函数的最值?
  8. AI智能电话客服机器人的交互流程
  9. 一张图让你知道什么是POE交换机
  10. 【2021-7月】渗透测试/安全服务实习生面试题经验分享