距离变换 Distance Transformation

以下为该学习地址的学习笔记:Distance transformation in image - Python OpenCV - GeeksforGeeks

 其他学习资料:Morphology - Distance Transform

简介

距离变换是一种用于计算图像中每个像素与最近的非零像素之间距离的技术。它通常用于图像分割和物体识别任务,因为它可以帮助识别图像中物体的边界。(如下图片来源于Chamani, H., Rabbani, A., Russell, K. P., Zydney, A. L., Gomez, E. D., Hattrick-Simpers, J., & Werber, J. R. (2023). Rapid reconstruction of 3-D membrane pore structure using a single 2-D Micrograph. arXiv preprint arXiv:2301.10601.)

1. 距离变换在OpenCV中的实现

OpenCV 中的距离变换函数 cv2.distanceTransform() 接收二值图像并返回两个数组:距离图像和标签图像(the distance image and the label image)。距离图像包含每个像素与最近的非零像素的距离值,标签图像包含最近的非零像素的标签。

#简单表示一下
dist_transform, labels = cv2.distanceTransform(binary_image, distance_type, mask_size)
  • binary_image: 输入的二值图像,非零像素通常表示前景对象。
  • distance_type: 距离类型,可以使用常量如cv2.DIST_L1(曼哈顿距离)或cv2.DIST_L2(欧几里得距离)。
  • mask_size: 掩码大小,确定用于计算距离的掩码的大小,值越大计算越精确但速度越慢。

距离类型

  • cv2.DIST_L1: 曼哈顿距离the Manhattan distance,即只计算水平和垂直方向的距离。
  • cv2.DIST_L2: 欧几里得距离the Euclidean distance,即计算实际的几何距离,包含所有方向。

掩码大小

掩码大小(mask size)决定了计算距离时使用的邻域范围,常用的大小有3、5等。较大的掩码可以提供更精确的距离值,但计算开销也会增加。

距离变换的结果

距离变换的结果是一个与原始图像大小相同的距离图像,每个像素值表示该像素到最近前景像素的距离。通过这种方式,可以有效地识别图像中对象的边界。

距离图像的归一化

为了方便可视化,OpenCV提供了cv2.normalize()函数,可以将距离图像的值归一化到0到255的范围内。

归一化

#简单表示一下
normalized_dist_transform = cv2.normalize(dist_transform, None, 0, 255, cv2.NORM_MINMAX)
  • dist_transform: 输入的距离图像。
  • None: 输出数组,通常设为None表示原地操作。
  • 0: 归一化后的最小值。
  • 255: 归一化后的最大值。
  • cv2.NORM_MINMAX: 归一化类型,将最小值和最大值归一化到指定范围。

除了距离变换函数外,OpenCV 还提供了 cv2.normalize() 函数,用于对距离图像进行归一化处理,使距离值在 0 到 255 之间。这对距离图像的可视化非常有用。

距离变换是一种图像处理技术,可用于获取图像中每个像素与最近的非零像素之间的距离。它常用于图像分割和物体识别任务。

2. 具体步骤

在 OpenCV 中,我们可以使用 cv2.distanceTransform() 函数执行距离变换。

需要遵循的步骤

  1. 加载图像:使用 cv2.imread() 函数加载图像。
  2. 转换为灰度图像:使用 cv2.cvtColor() 函数将图像转换为灰度图像。这是因为距离变换函数仅适用于单通道图像
  3. 创建二值图像:进行阈值处理,使用cv2.threshold()函数对图像进行二值化,将像素强度值大于某个阈值的像素设为255,其他像素设为0。
  4. 计算距离变换:使用cv2.distanceTransform()函数计算每个像素到最近非零像素的距离。该函数接受三个参数:二值图像、距离类型(如cv2.DIST_L2表示欧几里得距离)和掩码大小(如3表示3×3掩码)。
  5. 返回结果:距离变换函数返回两个数组:距离图像和标签图像。距离图像包含每个像素与最近的非零像素的距离值,标签图像包含最近的非零像素的标签。

3. 示例

3.1 示例 1

import cv2  # 导入OpenCV库# 加载图像
# 你可以提供图像的路径
image = cv2.imread(r"Mandala.jpg")  # 读取图像文件"Mandala.jpg"# 将图像转换为灰度图像
grayScaleImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 将彩色图像转换为灰度图像# 对图像进行二值化处理,创建二值图像
_, threshold = cv2.threshold(grayScaleImage, 123, 255, cv2.THRESH_BINARY)  # 将灰度图像进行二值化,阈值为123# 计算距离变换
# distTransform = cv2.distanceTransform(threshold, cv2.DIST_C, 3)  # 使用Chebyshev距离计算距离变换
# distTransform= cv2.distanceTransform(threshold, cv2.DIST_L1, 3)  # 使用曼哈顿距离计算距离变换
distTransform= cv2.distanceTransform(threshold, cv2.DIST_L2, 3)  # 使用欧几里得距离计算距离变换# 显示距离变换后的图像
cv2.imshow('Transformed Distance Image1', distTransform)  # 显示距离变换后的图像# 按任意键结束进程
cv2.waitKey(0)  # 等待按键输入
cv2.destroyAllWindows()  # 销毁所有窗口# 保存距离变换后的图像
cv2.imwrite('distTransformed.jpg', distTransform)  # 将距离变换后的图像保存为"distTransformed.jpg"

此代码的输出将是一个包含距离图像的窗口,其中每个像素包含与最近非零像素的距离值。距离值的范围为 0 到 255,值越大表示距离越大。

3.2 示例2(标签图像)

下面是OpenCV中距离变换的第二个示例代码,演示了如何使用标签图像获取图像中每个像素的最近非零像素的坐标:

# importing necessary libraries 
# 导入必要的库
import cv2  # 导入OpenCV库
import numpy as np  # 导入NumPy库,用于数组操作# Load the image 
# you can specify the path to image 
# 加载图像
# 你可以指定图像的路径
image = cv2.imread(r"Visual_arts.jpg")  # 读取图像文件"Visual_arts.jpg"# Convert the image to grayscale 
# 使用cv2.cvtColor()函数将图像转换为灰度图像
grayScaleImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Threshold the image to create a binary image 
# 使用cv2.threshold()函数对灰度图像进行二值化处理,创建二值图像
_, threshold = cv2.threshold(grayScaleImage, 127, 255, cv2.THRESH_BINARY) # Calculate the distance transform 
# 使用cv2.distanceTransform()函数计算二值图像的距离变换
dist, labels, *other_vars = cv2.distanceTransform(threshold, cv2.DIST_L2, 3) # Find the coordinates of the nearest non-zero pixels for each pixel in the image 
# 使用np.where()和np.column_stack()函数找到每个像素的最近非零像素的坐标
coords = np.column_stack(np.where(labels > 0)) # Print the coordinates 
# squeeze is used to remove the undesired dimension 
# 打印坐标
# 使用squeeze()函数去除不需要的维度
print(coords.squeeze())

输出:

[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1718 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3536 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 5354 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 7172 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 8990 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143144 151 152 156 157 158 159 160 161 162 163 167 168 169 170 171 172 179180 200 201 202 203 204 240 241 242 243 244 254 255 256 257 287 290 297]

代码片段补充介绍

_, threshold = cv2.threshold(grayScaleImage, 127, 255, cv2.THRESH_BINARY)
  • _:这个下划线通常用作占位符,表示在此处接收一个值但不需要使用它。在这里,它用于接收cv2.threshold()函数返回的第一个返回值,即阈值化操作后的阈值(threshold),但实际上在后续代码中并没有使用这个值。
  • threshold:这是一个变量名,用于接收cv2.threshold()函数返回的第二个返回值,即二值化后的图像。这是我们感兴趣的结果,它是一个灰度图像,其中像素值只有两种可能:0(黑色,表示背景)和255(白色,表示前景)。
  • cv2.THRESH_BINARY:这是cv2.threshold()函数的一个参数,用于指定阈值化类型。cv2.THRESH_BINARY表示二值阈值化类型,即将大于阈值的像素设置为一个值(这里是255),小于或等于阈值的像素设置为另一个值(这里是0)。
dist, labels, *other_vars = cv2.distanceTransform(threshold, cv2.DIST_L2, 3)
  • dist:这是一个变量名,用于接收cv2.distanceTransform()函数返回的第一个数组,即距离图像(distance image)。距离图像包含了每个像素到最近非零像素的距离值。
  • labels:这是一个变量名,用于接收cv2.distanceTransform()函数返回的第二个数组,即标签图像(label image)。标签图像包含了每个像素所属的最近非零像素的标签。
  • other_vars:这个是Python中的可变参数形式,用于接收cv2.distanceTransform()函数可能返回的额外的参数。在这个特定的情况下,cv2.distanceTransform()函数实际上只返回两个值(距离图像和标签图像),所以other_vars在这里实际上是一个空列表,因为没有额外的参数需要接收。
  • cv2.distanceTransform():这是OpenCV库中的一个函数,用于计算图像的距离变换。它接受以下参数:
    • threshold:输入的二值化图像,这里是前面阈值化得到的二值图像。
    • cv2.DIST_L2:距离的类型,这里选择欧几里得距离(L2范数),表示每个像素到最近非零像素的欧几里得距离。
    • 3:掩码大小,即用于计算距离的卷积核的大小,这里是3×3的卷积核。

补充掩码

  • 控制掩码的大小和形状可以影响操作的结果,例如在距离变换中,掩码的大小决定了计算每个像素到最近非零像素距离的精度和效率。
  • 在距离变换中,掩码用于计算每个像素到最近非零像素的距离。通常使用的掩码大小是一个正方形(3×3、5×5等),它定义了像素周围的邻域。
coords = np.column_stack(np.where(labels > 0)) 

np.where(labels > 0)

  • labels > 0:这是一个条件表达式,返回一个布尔类型的数组,数组的每个元素都是 labels 中对应位置的像素值是否大于0的判断结果。如果 labels 中的像素值大于0,则对应位置为True,否则为False。
  • np.where():这是一个NumPy函数,用于根据指定的条件返回符合条件的元素的索引。它可以接受一个条件表达式作为参数,并返回一个包含符合条件元素索引的元组。
    • 如果条件表达式是一个二维数组,np.where() 返回的是一个包含两个一维数组的元组,分别代表符合条件的行索引和列索引。
    • 如果条件表达式是一个一维数组,np.where() 直接返回符合条件的元素的索引。

在这里,np.where(labels > 0) 返回的是一个元组,其中包含了 labels 中大于0的像素点的索引。

np.column_stack()

  • np.column_stack():这是NumPy函数,用于将多个一维数组按列堆叠成一个二维数组。它接受一个元组或列表作为参数,参数中的每个元素是一个一维数组。

在这里,np.column_stack(np.where(labels > 0)) 接受了 np.where(labels > 0) 返回的元组作为参数,将其中的每个一维数组按列堆叠成一个二维数组。因为 np.where(labels > 0) 返回的是一个包含行索引和列索引的元组,所以 np.column_stack() 的作用是将这两个一维数组按列排列成一个二维数组,即将行索引和列索引对应堆叠在一起。

coords

  • coords:这是一个变量名,用于接收 np.column_stack(np.where(labels > 0)) 的结果。它表示了所有 labels 中大于0的像素点的坐标。

综合起来,coords = np.column_stack(np.where(labels > 0)) 这行代码的作用是找到 labels 图像中所有像素值大于0的像素点的坐标,并将这些坐标按列堆叠成一个二维数组,存储在 coords 变量中。

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

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

相关文章

51单片机5(GPIO简介)

一、序言:不论学习什么单片机,最简单的外设莫过于I口的高低电平的操作,接下来,我们将给大家介绍一下如何在创建好的工程模板上面,通过控制51单片机的GPIO来使我们的开发板上的LED来点亮。 二、51单片机GPIO介绍&#…

第三节SHELL脚本中的变量与运算(1.1-1.5)

一,脚本中的变量 1,1什么是变量 在编写程序是,通常会遇到被操作对象不固定的情况我们需要用一串固定的字符来的表示不固定的值,这就是变量存在的根本意义变量的实现原理就是内存存储单元的一个符合名称 1,2 变量的命名规则 变量的名称中只能包含数字,大小写字母以及下划线 …

PySide在Qt Designer中使用QTableView 显示表格数据

在 PySide6 中,可以使用 Qt Model View 架构中的 QTableView 部件来显示和编辑表格数据。 1、创建ui文件 在Qt Designer中新建QMainWindow,命名为csvShow.ui。QMainWindow上有两个部件:tableview和btn_exit。 2、使用pyuic工具将ui文件转换为…

Kafka(四) Consumer消费者

一,基础知识 1,消费者与消费组 每个消费者都有对应的消费组,不同消费组之间互不影响。 Partition的消息只能被一个消费组中的一个消费者所消费, 但Partition也可能被再平衡分配给新的消费者。 一个Topic的不同Partition会根据分配…

MySQL集群、Redis集群、RabbitMQ集群

一、MySQL集群 1、集群原理 MySQL-MMM 是 Master-Master Replication Manager for MySQL(mysql 主主复制管理器)的简称。脚本)。MMM 基于 MySQL Replication 做的扩展架构,主要用来监控 mysql 主主复制并做失败转移。其原理是将真…

环境变量在Gradle中的妙用:构建自动化的秘诀

环境变量在Gradle中的妙用:构建自动化的秘诀 在构建自动化的过程中,环境变量扮演着至关重要的角色。它们允许开发者根据不同的运行环境(如开发、测试和生产环境)来调整配置,而无需修改代码。Gradle,作为一…

基于Faster R-CNN的安全帽目标检测

基于Faster R-CNN的安全帽目标检测项目通常旨在解决工作场所,特别是建筑工地的安全监管问题。这类项目使用计算机视觉技术,特别是深度学习中的Faster R-CNN算法,来自动检测工人是否正确佩戴了安全帽,从而确保遵守安全规定并减少事…

实验一:图像信号的数字化

目录 一、实验目的 二、实验原理 三、实验内容 四、源程序及结果 源程序(python): 结果: 五、结果分析 一、实验目的 通过本实验了解图像的数字化过程,了解数字图像的数据矩阵表示法。掌握取样(象素个…

用Python爬虫能实现什么?得到什么?

Python爬虫是一种强大的工具,可以用来自动化地从互联网上抓取数据和信息。使用Python实现爬虫可以达成多种目的,包括但不限于以下几个方面: 数据收集: 网页内容抓取:可以抓取网页上的文本、图片、视频等内容。搜索引擎…

Linux 网络配置与连接

一、网络配置 1.1 ifconfig 网卡配置查询 ifconfig #查看所有启动的网络接口信息 ifconfig 指定的网卡 #查看指定网络接口信息 1.2 修改网络配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33 #ens33网络配置文…

【电源拓扑】反激拓扑

目录 工作模式 固定频率 CCM连续电流模式 DCM不连续电流模式 可变频率 CRM电流临界模式 反激电源CRM工作模式为什么要跳频 反激电源应用场景 为什么反激电源功率做不大 电感电流爬升 反激变压器的限制条件 精通反激电源设计的关键-反激电源变压器设计 反激电源变压…

MySQL 事务与锁

事务ACID特性 原子性:事务要么同时成功,要么同时失败,事务的原子性通过undo log日志保证 一致性:业务代码要抛出报错,让数据库回滚 隔离性:事务并发执行时,他们内部操作不能互相干扰 持久性&…

Python 读取esxi上所有主机的设备信息

(主要是为了统计所有虚拟机的设备名称和所属主机) 代码: from pyVim import connect from pyVmomi import vim import ssldef get_vm_devices(vm):devices []try:if vm.config is not None and hasattr(vm.config, hardware) and hasattr(v…

SpringBoot解决Apache Tomcat输入验证错误漏洞

Apache Tomcat是美国阿帕奇(Apache)基金会的一款轻量级Web应用服务器。该程序实现了对Servlet和JavaServer Page(JSP)的支持。 Apache Tomcat存在输入验证错误漏洞,该漏洞源于HTTP/2请求的输入验证不正确,会…

postgresql简单导出数据与手动本地恢复(小型数据库)

问题 需要每天手动备份postgresql。 步骤 导出数据 /opt/homebrew/opt/postgresql16/bin/pg_dump --file/Users/zhangyalin/backup_sql/<IP地址>_pg-2024_07_15_17_30_15-dump.sql --dbname<数据库名> --username<用户名> --host<IP地址> --port54…

Day53:图论 岛屿数量 岛屿的最大面积

99. 岛屿数量 时间限制&#xff1a;1.000S 空间限制&#xff1a;256MB 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成&#xff0c;并且四周…

低空经济持续发热,无人机培训考证就业市场及前景剖析

随着科技的不断进步和社会需求的日益增长&#xff0c;低空经济已成为全球及我国经济增长的新引擎。作为低空经济的重要组成部分&#xff0c;无人机技术因其广泛的应用领域和显著的经济效益&#xff0c;受到了社会各界的广泛关注。为满足市场对无人机人才的需求&#xff0c;无人…

深入剖析 Android 开源库 EventBus 的源码详解

文章目录 前言一、EventBus 简介EventBus 三要素EventBus 线程模型 二、EventBus 使用1.添加依赖2.EventBus 基本使用2.1 定义事件类2.2 注册 EventBus2.3 EventBus 发起通知 三、EventBus 源码详解1.Subscribe 注解2.注册事件订阅方法2.1 EventBus 实例2.2 EventBus 注册2.2.1…

梦想CAD在线预览编辑功能

1.最近有个需求&#xff0c;在web系统里进行在线进行CAD预览和编辑&#xff0c;这里用的是梦想CAD实现此功能&#xff0c;梦想CAD官网文档 2.CAD预览&#xff0c;需要需要对CAD文件格式进行转化&#xff0c;将dwg文件格式转化为mxweb格式&#xff0c;再进行调用梦想CAD里的打开…

ipynb转换为pdf、Markdown(.md)

Jupyter Notebook 文件&#xff08;.ipynb&#xff09;可以转换成多种数据格式&#xff0c;以适应不同的使用场景和需求。以下是几种常见的转换格式及其简洁描述&#xff1a; HTML: Jupyter Notebook可以直接导出为静态的网页&#xff08;HTML&#xff09;格式&#xff0c;这样…