距离变换 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介绍&#…

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 主主复制并做失败转移。其原理是将真…

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

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

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

目录 一、实验目的 二、实验原理 三、实验内容 四、源程序及结果 源程序(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…

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…

ipynb转换为pdf、Markdown(.md)

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

记一次IP数据处理过程,文本(CSV文件)处理,IP解析

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 起因 突然接收到XX给的任务&#xff0c;要将一批IP数据处理一下&#xff0c;将IP对应的省市区解析出来…

PHP智云物业管理平台微信小程序系统源码

​&#x1f3e0;智云物业管理新纪元&#xff01;微信小程序&#xff0c;让家园管理更智慧&#x1f4f1; &#x1f3e1;【开篇&#xff1a;智慧生活&#xff0c;从物业开始】&#x1f3e1; 在快节奏的现代生活中&#xff0c;我们追求的不仅仅是家的温馨&#xff0c;更是生活的…

基于hive数据库的泰坦尼克号幸存者数据分析

进入 ./beeline -u jdbc:hive2://node2:10000 -n root -p 查询 SHOW TABLES; 删除 DROP TABLE IF EXISTS tidanic; 上传数据 hdfs dfs -put train.csv /user/hive/warehouse/mytrain.db/tidanic 《泰坦尼克号幸存者数据分析》 1、原始数据介绍 泰坦尼克号是当时世界上…

达梦数据库系列—28. 主备集群高可用测试

目录 监视器关闭 监视器启动&#xff0c;Detach备库 主备正常&#xff0c;手动switchover 主库故障&#xff0c;自动switchover 主库故障&#xff0c;手动Takeover 主库故障&#xff0c;备库强制takeover 主库重启 备库故障 公网连接异常 主库私网异常 备库私网异常…

实现给Nginx的指定网站开启basic认证——http基本认证

一、问题描述 目前我们配置的网站内容都是没有限制&#xff0c;可以让任何人打开浏览器都能够访问&#xff0c;这样就会存在一个问题&#xff08;可能会存在一些恶意访问的用户进行恶意操作&#xff0c;直接访问到我们的敏感后台路径进行操作&#xff0c;风险就会很大&#xff…