OpenCV学习 基础图像操作(十六):图像距离变换

基础原理

顾名思义,我们可以利用像素之间的距离作为对该像素的一种刻画,并将其运用到相应的计算之中。然而,在一幅图像之中,某种类型的像素并不是唯一的,因此我门常计算的是一类像素到另一类的最小距离,并且如何去定义和求解对应的像素也是可以根据问题去选择的

朴素的来看,这是一个计算复杂度很高的运算,因为我们需要对两种类别中的像素进行两两遍历求得起距离才能找到最小距离,然而实际中我们会充分利用空间位置关系,以及采样的方法来加速这个算法过程。

下面参考Distance Transforms of Sampled Functions中所述,来简单地介绍一下整个算法的思路:

首先,我们从问题转换为数学表示,假设在坐标轴上,G= 0,...,n-1,有如下变换:

D_f(p)=\underset{q\in \mathfrak{g}}{min}(d(p,q)+f(q))

其中D_f为从q变换到p的距离,d(p,q)为度量距离的方式,q为坐标中任意一点,f(q)表示点q的集合

f(q) =\begin{cases} 0 & \text{ if } q\epsilon P \\ \infty & \text{ othersize} \end{cases}

最小值卷积

此处由于相似的形式,我们引入最小卷积,与正常的卷积一样最小卷积,遵守交换律与结合率。

(f\bigotimes g)(p)=\underset{q}{min}(f(q)+g(p-q))

上式中,我们假设在一维的轴上进行测量,那么将d(p,q)替换为g(p-q),则距离变换就变为了fgp处的卷积了。

式子的右半边是一个最优化问题,即调整q寻找到最小值,那么将左半边的卷积也写为与右边相似的形式,即将卷积拆为一下形式:

{\delta}'(q)=b(q)+min(\delta (p)+a(p,q))

{\delta}'(q)=b(q)+D_\delta (q)

经过这样的变换后,可以看到式子迭代已经将另一个点排除在外了,即所求解的是一个全局的值。但是由于空间中点与点是有一定顺序的,我们可以利用动态规划等手段,优化这个线性的求解过程,最终将算法复杂度由O(n^2)优化到O(n)

一维上的变换

结合实际例子来看一下,假设在数轴上使用欧式距离进行距离变换:

D_f(p)=\underset{q\in \mathfrak{g}}{min}((p-q)^2+f(q))

形象的可视化下,每一个可能的点p的距离变换后的值为

我们需要找到就是在各个点距离变换后,在点rq中的最小值处s,以此作为采样点,进行实际的剧离运算,s的计算可表示为:

s=\frac{(f(r)+r^2)-(f(q)+q^2)}{2r-2q}

我们从左往右,依次记录每个抛物线交点的下包络并存到v[i]中,下包络线的第 i 条抛物线低于其他抛物线的范围由 z[i]z[i+1]给出,k表示第几根抛物线。则推理计算过程可以写为:

可视化其中s的更新过程为下图:

API介绍


void cv::distanceTransform	(	InputArray 	src,  //输入的原图
OutputArray 	dst,                              //输出的距离变换map
OutputArray 	labels,                           //输出的标签map
int 	distanceType,                             //距离的类型
int 	maskSize,                                 //距离变换掩码矩阵的大小
int 	labelType = DIST_LABEL_CCOMP              //类别的类型
)		

这意味着,对于一个像素,该函数会找到到最接近的零像素的最短路径,该路径由基本位移组成:水平、垂直、对角线或骑士移动(最新的可用于5×5面具)。总距离计算为这些基本距离的总和。由于距离函数应该是对称的,因此所有水平和垂直移动必须具有相同的成本(表示为 ),所有对角线移动必须具有相同的成本(表示为 ),并且所有骑士的移动必须具有相同的成本(表示为 )。对于DIST_C和DIST_L1类型,距离是精确计算的,而对于DIST_L2(欧几里得距离),距离只能通过相对误差(abc5×5mask 提供更准确的结果)。对于 、 和 ,OpenCV 使用原始论文中建议的值:abc

  • DIST_L1:a = 1, b = 2
  • DIST_L2:
    • 3 x 3:a=0.955, b=1.3693
    • 5 x 5:a=1, b=1.4, c=2.1969
  • DIST_C:a = 1, b = 1

通常,对于快速、粗略的距离估计DIST_L2,一个3×3使用面具。为了更准确地估计距离DIST_L2,一个5×5掩码或使用精确算法。请注意,精确算法和近似算法在像素数上都是线性的。

该函数的此变体不仅计算每个像素的最小距离(x,y)还可以标识由零像素 (labelType==DIST_LABEL_CCOMP) 或最接近的零像素 (labelType==DIST_LABEL_PIXEL) 组成的最近连接组件。分量/像素的索引存储在 中。当 labelType==DIST_LABEL_CCOMP 时,该函数会自动在输入图像中查找零像素的连接组件,并用不同的标签标记它们。当 labelType==DIST_LABEL_PIXEL 时,该函数会扫描输入图像,并使用不同的标签标记所有零像素。labels(x, y)

在这种模式下,复杂度仍然是线性的。也就是说,该函数提供了一种非常快速的方法来计算二进制图像的 Voronoi 图。目前,第二个变体只能使用近似距离变换算法,即尚不支持 maskSize=DIST_MASK_PRECISE。

简单使用一下,来找一下毛笔字的骨骼,自制一个描红本

import cv2
import matplotlib.pyplot as plt
def main():#读取图像img = cv2.imread("D:\code\src\code\zhen.jpg",cv2.IMREAD_GRAYSCALE)#二值化分割thresh,binary = cv2.threshold(img,50,255,cv2.THRESH_BINARY_INV)#利用距离变换找到骨骼脉络dist = cv2.distanceTransform(binary,cv2.DIST_L2,3)#利用自适应二值化保存脉络上局部最大值sk = cv2.adaptiveThreshold(dist.astype("uint8"),255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,9,0)plt.subplot(411),plt.imshow(img,cmap='gray'),plt.title('Source Image'), plt.xticks([]), plt.yticks([])plt.subplot(412),plt.imshow(binary,cmap='gray'),plt.title('Binary Image'), plt.xticks([]), plt.yticks([])plt.subplot(413),plt.imshow(dist),plt.title('Dist Map'), plt.xticks([]), plt.yticks([])plt.subplot(414),plt.imshow(sk,cmap='gray'),plt.title('Skelet Image'), plt.xticks([]), plt.yticks([])plt.show()if __name__ == "__main__":main() 

参考链接

[OpenCV] 图像分割之利用 cv2.distanceTransform 提取前景-CSDN博客

OpenCV学习三十五:distanceTransform 距离变换函数_c++ opencv distancetransform-CSDN博客OpenCV—python 图片细化(骨架提取)二_opencv骨架提取算法函数-CSDN博客

Distance Transforms of Sampled Functions (theoryofcomputing.org)

OpenCV:基于距离变换和分水岭算法的图像分割

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

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

相关文章

工厂模式详情

一.介绍工厂模式的用途与特点 工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。定义工厂方法模式(Fatory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例…

npm install node-sass 安装失败的解决方案:利用国内镜像加速安装

在开发前端项目时,使用Sass作为CSS预处理器是很多开发者的选择。然而,在通过npm安装其Node.js绑定库node-sass时,一些开发者可能会遇到安装失败的问题,尤其是网络原因导致的下载缓慢或中断。本文将指导你如何通过更换为国内镜像源…

如何在测试/线上环境页面访问本地接口?

文章目录 一、前言二、分析三、搭建1、搭建nginx,监听http请求转发2、监听https请求转发 四、总结 一、前言 在工作中,开发完的接口,一般测试的话,基本是使用Postman,如果要到页面测试,就要发版进行测试&a…

《逆水寒》手游周年庆,热度不减反增引发热议

易采游戏网5月31日最新消息:随着数字娱乐时代的飞速发展,手游市场的竞争愈发激烈。在这样的大背景下,《逆水寒》手游以其独特的古风武侠世界和深度的社交体验,自上线以来便吸引了无数玩家的目光。如今,这款游戏迎来了它…

知识运维概述

文章目录 知识运维研究现状技术发展趋势 知识运维 由于构建全量的行业知识图谱成本很高,在真实的场景落地过程中,一般遵循小步快走、快速迭代的原则进行知识图谱的构建和逐步演化。知识运维是指在知识图谱初次构建完成之后,根据用户的使用反馈…

WSL2-Ubuntu22.04-配置

WSL2-Ubuntu22.04-配置 准备1. WSL相关命令[^1]2. WSL2-Ubuntu22.04可视化3. WSL2 设置 CUDA4. 设置OpenGL 本文介绍了WSL2的基本使用方法及可视化,着重介绍了GPU和OpenGL的设置。 准备 名称版本windows11wsl2CUDA12.5 1. WSL相关命令1 查看已安装的wsl distribut…

DevExpress开发WPF应用实现对话框总结

说明: 完整代码Github​(https://github.com/VinciYan/DXMessageBoxDemos.git)DevExpree v23.2.4(链接:https://pan.baidu.com/s/1eGWwCKAr8lJ_PBWZ_R6SkQ?pwd9jwc 提取码:9jwc)使用Visual St…

“手撕”链表的九道OJ习题

目录 1. 第一题 2. 第二题 3. 第三题 4. 第四题 5. 第五题 6. 第六题 7. 第七题 8. 第八题 9. 第九题 1. 第一题 删除链表中等于给定值 val 的所有节点。OJ链接 思路如下: 相当于链表的removeAll();制定prev和cur,prev记录前一个节点&#xff…

2021JSP普及组第三题:插入排序

2021JSP普及组第三题 题目: 思路: 题目要求排序后根据操作进行对应操作。 操作一需要显示某位置数据排序后的位置,所以需要定义结构体数组储存原数据的位置和数据本身排序后所得数据要根据原位置输出排序后的位置,所以建立一个新…

作业 递归应用

已完成&#xff1a;7 #include <iostream> using namespace std; long long f(long long,long long); int main(){long long n,m;cin>>n>>m;cout<<f(m,n);return 0; } long long f(long long a,long long b){if(a%b0){return b;}return f(b,a%b); } #i…

RedisSearch与Elasticsearch:技术对比与选择指南

码到三十五 &#xff1a; 个人主页 数据时代&#xff0c;全文搜索已经成为许多应用程序中不可或缺的一部分。RedisSearch和Elasticsearch是两个流行的搜索解决方案&#xff0c;它们各自具有独特的特点和优势。本文简单探讨一些RedisSearch和Elasticsearch之间的技术差异。 目录…

软件测试基础

目录 一.基础 1.概念 1.1 什么是软件测试&#xff1f; 1.2 什么是需求&#xff1f; 1.3 什么是测试用例&#xff1f; 1.4 为什么需要测试用例&#xff1f; 1.5 什么是BUG&#xff1f; 1.6 软件生命周期 2.开发模型 2.1 瀑布模型 2.2 螺旋模型 2.3 增量模型、迭代模型…

从零到一建设数据中台 - 关键技术汇总

一、数据中台关键技术汇总 语言框架&#xff1a;Java、Maven、Spring Boot 数据分布式采集&#xff1a;Flume、Sqoop、kettle 数据分布式存储&#xff1a;Hadoop HDFS 离线批处理计算&#xff1a;MapReduce、Spark、Flink 实时流式计算&#xff1a;Storm/Spark Streaming、…

(CPU/GPU)粒子继承贴图颜色发射

GetRandomInfo节点(复制贴进scratch pad Scripts) Begin Object Class/Script/NiagaraEditor.NiagaraClipboardContent Name"NiagaraClipboardContent_22" ExportPath/Script/NiagaraEditor.NiagaraClipboardContent"/Engine/Transient.NiagaraClipboardConten…

安装软件缺少dll文件怎么办,分享多种解决dll问题的方法

在计算机使用过程中&#xff0c;我们经常会遇到安装软件时提示缺少dll文件的问题。这种情况通常会导致软件无法正常运行或启动。为了解决这个问题&#xff0c;我总结了以下五种方法&#xff0c;希望对大家有所帮助。 一&#xff0c;了解DLL文件是什么 动态链接库&#xff08;D…

连通块中点的数量-java

本次我们通过连通块中点的数量来加深我们对并查集的基本操作和原理&#xff0c;并且知道如何在并查集中添加附属信息。 目录 前言☀ 一、连通块中点的数量☀ 二、算法思路☀ 1.无向图&#x1f319; 2.在a b之间连一条边&#xff0c;a b可能相等&#x1f319; 3.询问a和b是否在一…

Java | Leetcode Java题解之第122题买卖股票的最佳时机II

题目&#xff1a; 题解&#xff1a; class Solution {public int maxProfit(int[] prices) {int ans 0;int n prices.length;for (int i 1; i < n; i) {ans Math.max(0, prices[i] - prices[i - 1]);}return ans;} }

一维时间序列信号的小波模极大值分解与重建(matlab R2018A)

数学上称无限次可导函数是光滑的或没有奇异性&#xff0c;若函数在某处有间断或某阶导数不连续&#xff0c;则称函数在此处有奇异性&#xff0c;该点就是奇异点。奇异性反映了信号的不规则程度&#xff0c;因为信号的奇异点和突变部分往往携带者重要信息&#xff0c;因此信号的…

传感器和变送器的区别介绍

从它的名称来看&#xff0c;传与感二字。传是指传输&#xff0c;感是指感知。实际上是先有感知&#xff0c;其次转换&#xff0c;最后传输。因此传输是目的&#xff0c;转换是手段&#xff0c;感知是基础。把能够将被测变量&#xff08;温度、压力、液位、流量&#xff09;感知…

Go-Admin后台管理系统源码(GO+VUE)编译与部署

1.克隆源码: # Get backend code git clone https://github.com/go-admin-team/go-admin.git# Get the front-end code git clone https://github.com/go-admin-team/go-admin-ui.git3.下载并安装GO开发环境: 3.编译管理后台后端 # Enter the go-admin backend project cd ./…