计算机视觉 | 基于二值图像数字矩阵的距离变换算法

news2025/6/14 15:11:25

Hi,大家好,我是半亩花海。本实验基于 OpenCV 实现了二值图像数字矩阵的距离变换算法。首先生成一个 480x480 的黑色背景图像(定义黑色为0,白色为1),在其中随机选择了三个白色像素点作为距离变换的原点,利用 OpenCV 中 distanceTransform 等相关函数计算并输出这些原点到其他像素点的欧氏距离、D4 距离和 D8 距离及其相应的距离矩阵,并将距离变换结果可视化

文章目录

  • 一、导入必要库
  • 二、初始化输入图像和变换结果图像
  • 三、根据二值图计算并输出距离矩阵
  • 四、将距离矩阵转换为可视化图片

一、导入必要库

导入必要的库(cv2、numpy、matplotlib.pyplot),为后续的图像处理任务做准备。

#!/usr/bin/env python
# coding: utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 用来设置字体样式(黑体)以正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

二、初始化输入图像和变换结果图像

自定义 480x480 二值图,随机生成图案,初始值都是 0(黑色),并显示原始图像。

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

    • 采样: 对连续函数 f ( x , y ) f(x,y) f(x,y) 进行采样,就是分别对 x x x 轴和 y y y 轴,按照固定间隔取值,得到平面坐标上的 M × N M×N M×N 个点,将其函数值作为元素生成 M M M N N N 列的矩阵。

    • 量化亮度值。 f ( x , y ) f(x,y) f(x,y) 的值转化为等价的整数值的过程称为量化,量化的级别越高,图像越细致。通常将亮度值表示为 0~255 之间的整数。

# 创建一个大小为 480x480 的全黑图像(确保数据类型为 8 位无符号整数)
mat = np.zeros((480, 480), dtype=np.uint8)
# 给输入图像指定三个像素点设置为白色像素,作为距离变换原点(区域块)
mat[100, 200] = 1
mat[200, 100] = 1
mat[300, 300] = 1

# 显示原始图像和距离变换结果
plt.figure(figsize=(15, 5))
plt.scatter([100, 200, 300], [200, 100, 300], color='white', marker='o')  # 添加三个白点表示出三个像素点的坐标
plt.imshow(mat, cmap='gray')
plt.title('原始图像', fontsize=16)
# 将输入图像中 1(白色)和 0(黑色)调换,使得原点距离为 0
mat = 1 - mat

三、根据二值图计算并输出距离矩阵

  • 距离: 距离是描述图像两点像素之间的远近关系的度量,常见的度量距离有欧式距离(Euchildean distance)、城市街区距离(City block distance)、棋盘距离(Chessboard distance)。以下以两坐标点 a = ( i , j ) a = (i, j) a=(i,j) b = ( k , l ) b = (k, l) b=(k,l) 的距离为例,来说明各种距离的定义方式。

(1)欧式距离 D e D_e De 欧式距离的定义源于经典的几何学,与我们数学中所学的简单几何的两点之间的距离一致,为两个像素点坐标值的平方根。欧式距离的优点在于其定义非常地直观,是显而易见的,但缺点在于平方根的计算是非常耗时的。

D e ( a , b ) = ( ( i − k ) 2 ) + ( j − l ) 2 D_e(a, b)=\sqrt{\left((i-k)^2\right)+(j-l)^2} De(a,b)=((ik)2)+(jl)2

(2)城市街区距离 D 4 D_4 D4 距离描述的是只允许像素坐标系平面中横向和纵向的移动距离,4表示在这种定义下,像素点是 4 邻接的,即每个点只与它的上、下、左、右相邻的 4 个点之间的距离为 1。

D 4 ( a , b ) = ∣ i − k ∣ + ∣ j − l ∣ D_4(a, b)=|i-k|+|j-l| D4(a,b)=ik+jl

(3)棋盘距离 D 8 D_8 D8 如果允许在图像坐标系中像素点的对角线方向的移动,就可以得到棋盘距离,8 表示在这种定义下,像素点是 8 邻接的,即每个点只与它的上、下、左、右、四个对角线方向相邻的 8 个点之间的距离为 1。

D 8 ( a , b ) = max ⁡ { ∣ i − k ∣ , ∣ j − l ∣ } D_8(a, b)=\max \{|i-k|,|j-l|\} D8(a,b)=max{ik,jl}

  • 距离变换

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

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

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

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

(1) 建立一个大小为 M × N M×N M×N 的数组 F F F,作如下的初始化:将区域块中的元素设置为 0,其余元素设置为无穷;

(2) 利用掩模1(mask1),左上角开始,从左往右,从上往下遍历数组,将掩模中P点对应的元素的值作如下更新:

F ( P ) = min ⁡ q ∈ mask1 ⁡ { F ( P ) , D ( P , q ) + F ( q ) } F(P)=\min _{q \in \operatorname{mask1}}\{F(P), D(P, q)+F(q)\} F(P)=qmask1min{F(P),D(P,q)+F(q)}

(3) 利用掩模2(mask2),右下角开始,从右往左,从下往上遍历数组,将掩模中P点对应的元素的值作如下更新:

F ( P ) = min ⁡ q ∈ mask2 ⁡ { F ( P ) , D ( P , q ) + F ( q ) } F(P)=\min _{q \in \operatorname{mask2}}\{F(P), D(P, q)+F(q)\} F(P)=qmask2min{F(P),D(P,q)+F(q)}

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

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

在 OpenCV 中,distanceTransform 函数是用于计算二进制图像中每个非零像素到最近零像素的距离的函数。这个函数通常用于图像处理中的形态学操作和特征提取。下面是 distanceTransform 函数的一般形式:

dist_transform = cv2.distanceTransform(src, distanceType, maskSize)

  • src: 是输入的二进制图像(该图像应该是一个 8 位单通道图像)。

  • distanceType: 是指定距离度量的类型。

  • maskSize: 是指定计算距离时使用的卷积核的大小。

# 分别利用欧式距离、D4 距离和 D8 距离作距离变换
transMatE = cv2.distanceTransform(mat, distanceType=cv2.DIST_L2, maskSize=0)  # 计算欧氏距离变换
transMatD4 = cv2.distanceTransform(mat, distanceType=cv2.DIST_L1, maskSize=0)  # 计算 D4 距离变换
transMatD8 = cv2.distanceTransform(mat, distanceType=cv2.DIST_C, maskSize=0)  # 计算 D8 距离变换
# 输出欧式、D4 和 D8 的距离矩阵
print("欧氏距离的变换矩阵:\n", transMatE)
print("城区距离-D4的变换矩阵:\n", transMatD4)
print("棋盘距离-D8的变换矩阵:\n", transMatD8)

四、将距离矩阵转换为可视化图片

因为经过距离矩阵变换之后,变换结果的数据类型为 float32(32 位浮点数),而在 OpenCV 中,采用 imshow 函数显示图像时需要使用 uint8 数据类型(8 位无符号整数),使得像素值的范围是从 0~255,可以表示灰度图像中的所有可能像素值。而 Matplotlib 可以直接处理 float32 类型的图像数据,因此并不需要将图像数据类型转换为 uint8 类型。

plt.figure(figsize=(15, 5))

plt.subplot(1, 3, 1)
plt.imshow(transMatE, cmap='gray')
plt.title('欧氏距离', fontsize=16)
plt.colorbar(shrink=0.8)

plt.subplot(1, 3, 2)
plt.imshow(transMatD4, cmap='gray')
plt.title('城区距离-D4', fontsize=16)
plt.colorbar(shrink=0.8)

plt.subplot(1, 3, 3)
plt.imshow(transMatD8, cmap='gray')
plt.title('棋盘距离-D8', fontsize=16)
plt.colorbar(shrink=0.8)

plt.tight_layout()
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1585653.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务学习2

目录 一.网关路由 1.1.认识网关 1.2网关快速入门 1.2.1.创建项目 1.2.2.引入依赖 1.2.3.启动类 1.2.4.配置路由 1.3.路由过滤 二.网关登录校验 2.1网关请求处理流程 2.2网关过滤器 2.2.2网关过滤器 2.3自定义GlobalFilter 2.4.登录校验 2.4.1.JWT工具 2.4.2.登…

中文自然语言处理流程

这是博主自己根据网上资料进行整理的,希望对你有所帮助~

openlayer实现webgis端绘制制图及编辑

在WebGIS端制图是指通过Web浏览器界面实现地理信息数据的可视化、编辑、分析以及地图产品的制作。这一过程通常涉及以下几个关键环节: **1. 前端技术栈: •HTML/CSS/JavaScript:作为Web开发的基础,用于构建用户界面布局、样式设…

【线段树】2213. 由单个字符重复的最长子字符串

算法可以发掘本质,如: 一,若干师傅和徒弟互有好感,有好感的师徒可以结对学习。师傅和徒弟都只能参加一个对子。如何让对子最多。 二,有无限多1X2和2X1的骨牌,某个棋盘若干格子坏了,如何在没有坏…

Compose UI 之 Card 卡片组件

Card Card 是用于显示带有圆角和可选阴影的矩形内容容器。它通常用于构建用户界面,并可以包含标题、文本、图像、按钮等元素,表示界面上的可交互元素,我们称它是 “卡片”。 Card 使用的一些经典的场景: 列表数据,例如 新闻列表,产品列表等。信息提示框,使用 Card 组件…

Canon佳能打印机在扫描时会提示缺少组件解决方法

问题截图 解决方法 1.复制佳能驱动网址:下载与支持 – 服务与支持 - 佳能(中国)到浏览器访问,输入打印机型号,点击驱动程序。 2.在驱动程序栏目下,下载并安装打印机驱动。 3.点击应用程序栏目,…

计算机中的数字表示:正码、反码和补码

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 在计算机科学领域,数字表示是一个基础而且至关重要的概念。正码、反码和补码是计算机中常 目录 &am…

uniapp开发小程序,实现堆叠卡片轮播图

一、实现堆叠卡片轮播图: 需求: 实现堆叠轮播图效果堆叠到后面的图片有虚化效果可以在堆叠图片上写文字或叠加图片等效果可以手动滑动&#xff0c;也可以定时自动轮播 二、代码实现&#xff1a; 1.封装一个组件myswiper.vue <!-- 折叠轮播图 组件--> <template>…

Linux从入门到精通 --- 3.用户、权限

文章目录 第三章&#xff1a;3.1 root用户3.1.1 su3.1.2 exit3.1.3 sudo 3.2 用户和用户组3.2.1 用户组管理创建用户组删除用户组 3.2.2 用户管理创建用户删除用户查看用户所属组修改用户所属组 3.2.3 getent一&#xff1a;二&#xff1a; 3.3 查看权限控制信息3.3.1 认知权限信…

蓝桥杯算法题:栈(Stack)

这道题考的是递推动态规划&#xff0c;可能不是很难&#xff0c;不过这是自己第一次靠自己想出状态转移方程&#xff0c;所以纪念一下&#xff1a; 要做这些题目&#xff0c;首先要把题目中会出现什么状态给找出来&#xff0c;然后想想他们的状态可以通过什么操作转移&#xf…

DSP笔记8-通用GPIO

电源类 AD引脚类 系统相关JTAG 时钟 GPIO (general purpose input output)复用&#xff0c; 复用&#xff0c;I/O引脚&#xff0c;外设的功能引脚&#xff0c; 88个GPIO引脚&#xff0c;通用的输入输出口&#xff0c;功能复用的。 GPIO特点 输入电平与TTL电平兼容。>2.0V…

html 实现多个文本内容,轮播效果类似gif图片

前几日&#xff0c;产品要求后端实现一个将文字转为gif图片&#xff0c;要用于官网首页广告栏。我想这不是前段就能实现吗&#xff0c;怎么还要求后端生成gif&#xff0c;然后前段在展示。你确定招的前段不是对手公司过来的卧底&#xff1f;&#xff1f;&#xff1f; <!DOCT…

SSL中的CA证书

目录 一、CA概述 二、数据加密 三、身份认证 一、CA概述 SSL如何保证网络通信的安全和数据的完整性呢&#xff1f;就是采用了两种手段&#xff1a;身份认证和数据加密。身份认证就需要用到CA证书。 CA是证书的签发机构&#xff0c;它是公钥基础设施&#xff08;Public Key In…

neo4j-01

Neo4j是&#xff1a; 开源的&#xff08;社区版开源免费&#xff09;无模式&#xff08;不用预设数据的格式&#xff0c;数据更加灵活&#xff09;noSQL&#xff08;非关系型数据库&#xff0c;数据更易拓展&#xff09;图数据库&#xff08;使用图这种数据结构作为数据存储方…

腾讯云4核8G服务器多少钱?4核8G能干啥?

腾讯云4核8G服务器多少钱&#xff1f;腾讯云4核8G轻量应用服务器12M带宽租用价格646元15个月&#xff0c;活动页面 txybk.com/go/txy 活动链接打开如下图所示&#xff1a; 腾讯云4核8G服务器优惠价格 这台4核8G服务器是轻量应用服务器&#xff0c;详细配置为&#xff1a;轻量4核…

USB主机驱动分析

对于usb控制器来讲&#xff0c;不管是dwc3,还是xhci,ehci,ohci这些接口标准&#xff1b;如果半导体厂商是用这些标准来实现的usb控制器&#xff1b;那他们基本上给可以用这些核的通用驱动&#xff0c;因为通用寄存器都是一致的。 在Linux内核中&#xff0c;用usb_hcd结构体描述…

C++初阶 | [十二] 模板进阶

摘要&#xff1a;非类型模板参数&#xff0c;类模板的特化&#xff0c;模板的分离编译&#xff0c;模板总结 前言&#xff1a;C初阶终篇 1. 非类型模板参数 类型模板参数&#xff1a;如下代码&#xff0c;T 为模板的类型参数。 #define N 10 template<class T> class …

如何理解单片机 pwm 控制的基本原理?

单片机PWM&#xff08;脉宽调制&#xff09;控制的基本原理&#xff0c;简而言之&#xff0c;就是通过改变脉冲信号的宽度&#xff08;占空比&#xff09;来控制模拟电路。这涉及到单片机生成一系列脉冲信号&#xff0c;每个脉冲信号的高电平持续时间和整个周期的比值&#xff…

4051A/B/C/D/E–S信号/频谱分析仪

4051A/B/C/D/E–S信号/频谱分析仪 频段26.5GHz 计数分辨率0.001Hz 同轴频率26.5GHz 4051-S系列信号/频谱分析仪可广泛应用于移动通信、汽车电子、物联网、半导体等领域的信号及设备测试。 PART.01 产品综述 —— 频率范围覆盖&#xff1a;9kHz~26.5GHz# 4051-S系列信号/频…

一起找bug之购物

如果不是购物车满了&#xff0c;大概都不会发现这个 bug 淘宝 APP 修复了购物车满的情况下&#xff0c;往里面添加新商品时&#xff0c;会把一个老商品移入收藏夹&#xff0c; 但是如果这个老商品是已失效状态&#xff0c;就无法自动移入收藏夹&#xff0c;而且会一直在购物车…