OpenCV实现图像距离变换

图像中两个像素之间的距离有多种定义方式,图像处理中常用的距离有欧式距离、街区距离棋盘距离

欧式距离 略

街区距离

两个像素点X方向和Y方向的距离之和。欧式距离表示的是从一个像素点到另一个像素点的最短距离,然而有时我们并不能以两个点之间连线的方向前进,例如在一个城市内两点之间的连线可能存在障碍物的阻碍,因此从一个点到另一个点需要沿着街道行走,因此这种距离的度量方式被称为街区距离。街区距离就是由一个像素点到另一个像素点需要沿着X方向和Y方向一共行走的距离,数学表示形式如式所示。

棋盘距离

两个像素点X方向距离和Y方向距离的最大值。与街区距离相似,棋盘距离也是假定两个像素点之间不能够沿着连线方向靠近,像素点只能沿着X方向和Y方向移动,但是棋盘距离并不是表示由一个像素点移动到另一个像素点之间的距离,而是表示两个像素点移动到同一行或者同一列时需要移动的最大距离,数学表示形式如式所示。

CV_EXPORTS_AS(distanceTransformWithLabels) void distanceTransform( InputArray src, OutputArray dst,
                                     OutputArray labels, int distanceType, int maskSize,
                                     int labelType = DIST_LABEL_CCOMP );
  • src:输入图像,数据类型为CV_8U的单通道图像
  • dst:输出图像,与输入图像具有相同的尺寸,数据类型为CV_8U或者CV_32F的单通道图像。
  • labels:二维的标签数组(离散Voronoi图),与输入图像具有相同的尺寸,数据类型为CV_32S的单通道数据。
  • distanceType:选择计算两个像素之间距离方法的标志,其常用的距离度量方法在表6-1给出。
  • maskSize:距离变换掩码矩阵的大小,参数可以选择的尺寸为DIST_MASK_3(3×3)和DIST_MASK_5(5×5).
  • labelType:要构建的标签数组的类型,可以选择的参数在表给出。

  • 该函数用于实现图像的距离变换,即统计图像中所有像素距离0像素的最小距离。
  • 函数的第一个参数为待距离变换的输入图像,输入图像要求必须是CV_8U的单通道图像。
  • 函数第二个参数是原图像距离变换后的输出图像,与输入图像具有相同的尺寸,图像中每个像素值表示该像素在原图像中距离0像素的最小距离。由于图像的尺寸可能大于256,因此图像中某个像素距离0像素的最近距离有可能会大于255,为了能够正确的统计出每一个像素距离0像素的最小距离,输出图像的数据类型可以选择CV_8U或者CV_32F。
  • 函数第三个参数是原图像的Voronoi图,输出图像是数据类型为CV_32S单通道图像,图像尺寸与输入图像相同。
  • 函数第四个参数是距离变换过程中使用的距离种类,常用的距离为欧式距离(DIST_L2)、街区距离(DIST_L1)和棋盘距离(DIST_C)。
  • 函数第五个参数是求取路径时候的掩码尺寸,该尺寸与选择的距离种类有着密切的关系,当选择使用街区距离时,掩码尺寸选择3×3还是5×5对计算结果都没有影响,因此为了加快函数运算速度,默认选择掩码尺寸为3×3;当选择欧式距离时,掩码尺寸为3×3时是粗略的计算两个像素之间的距离,而当掩码尺寸为5×5时是精确的计算两个像素之间的距离,精确计算与粗略计算两者之间存在着较大的差异,因此在使用欧式距离时推荐使用5×5掩码;当选择棋盘距离时,掩码的尺寸对计算结果也没有影响,因此可以随意选择。
  • 函数的最后一个参数为构建标签数组的类型,当labelTypeDIST_LABEL_CCOMP时,该函数会自动在输入图像中找到0像素的连通分量,并用不同的标签标记它们。当labelTypeDIST_LABEL_CCOMP时,该函数扫描输入图像并用不同的标签标记所有0像素。

该函数原型在对图像进行距离变换的同时会生成Voronoi图,但是有时只是为了实现对图像的距离变换,并不需要使用Voronoi图,而使用该函数必须要求创建一个Mat类变量用于存放Voronoi图,占用了内存资源,因此distanceTransform()函数的第二种函数原型中取消了生成Voronoi图,只输出距离变换后的图像

void distanceTransform( InputArray src, OutputArray dst,
            int distanceType, int maskSize, int dstType=CV_32F); 
  • src:输入图像,数据类型为CV_8U的单通道图像
  • dst:输出图像,与输入图像具有相同的尺寸,数据类型为CV_8U或者CV_32F的单通道图像。
  • distanceType:选择计算两个像素之间距离方法的标志,其常用的距离度量方法在表6-1给出。
  • maskSize:距离变换掩码矩阵的大小,参数可以选择的尺寸为DIST_MASK_3(3×3)和DIST_MASK_5(5×5)。
  • dstType:输出图像的数据类型,可以是CV_8U或者CV_32F。

该函数原型中的主要参数含义与前一种函数原型相同,前两个参数为输入图像和输出图像,第三个参数和为距离变换过程中使用的距离种类。函数中第四个参数是距离变换掩码矩阵的大小,由于街区距离(Dist_L1)和棋盘距离(Dist_C)对掩模尺寸没有要求,因此该参数在选择街区距离和棋盘距离时被强制设置为3,同样掩模尺寸的大小对欧式距离(Dist_L2)计算的精度有影响,为了获取较为精确的时,一般使用5×5的掩模矩阵。函数最后一个参数是输出图像的数据类型,虽然可以在CV_8U和CV_32F两个类型中任意选择,但是图像输出时实际的数据类型与距离变换时选择的距离种类有着密切的联系,CV_8U只能使用在计算街区距离的条件下,当计算欧式距离和棋盘距离时,即使该参数设置为CV_8U,实际的输出图像的数据类型也是CV_32F。

简单示例

//
// Created by smallflyfly on 2021/6/15.
//

#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include "utils.hpp"

#include <iostream>

using namespace std;
using namespace cv;

int main() {

    // 自定义矩阵
    Mat a = (Mat_<uchar>(5, 5) <<
            1,1,1,1,1,
            1,1,1,1,1,
            1,1,0,1,1,
            1,1,1,1,1,
            1,1,1,1,1
            );
    Mat distL1, distL2, distC;
    distanceTransform(a, distL1, DIST_L1, 3, CV_8U);
    distanceTransform(a, distL2, DIST_L2, 5, CV_8U);
    distanceTransform(a, distC, DIST_C, 3, CV_8U);

    cout << distL1 << endl;
    cout << distL2 << endl;
    cout << distC << endl;

    Mat im = imread("test.jpg", IMREAD_GRAYSCALE);
    if (im.empty()) {
        cerr << "image file read error" << endl;
        return -1;
    }
    resize(im, im, Size(0, 0), 0.5, 0.5);

    // 转为二值图像
    Mat im1, im2;
    threshold(im, im1, 125 ,255, THRESH_BINARY);
    threshold(im, im2, 125, 255, THRESH_BINARY_INV);

    Mat dist1, dist2;
    distanceTransform(im1, dist1, DIST_L1, 3, CV_32F);
    distanceTransform(im2, dist2, DIST_L1, 3, CV_8U);

    showImage("im1", im1);
    showImage("dist1", dist1);
    showImage("im2", im2);
    showImage("dist2", dist2);

    waitKey(0);
    destroyAllWindows();

    return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • OpenCV图像处理之常见的图像灰度变换

    1.灰度线性变换 图像的灰度线性变换是图像灰度变换的一种,图像的灰度变换通过建立灰度映射来调整源图像的灰度,从而达到图像增强的目的.灰度映射通常是用灰度变换曲线来进行表示.通常来说,它是将图像的像素值通过指定的线性函数进行变换,以此来增强或者来减弱图像的灰度,灰度线性变换的函数就是常见的线性函数. g(x, y) = k · f(x, y) + d 设源图像的灰度值为x,则进行灰度线性变换后的灰度值为y = kx + b (0<=y<=255),下面分别来讨论k的取值变化时线性变换的不同效果

  • Opencv实现图像灰度线性变换

    本文实例为大家分享了Opencv实现图像灰度线性变换的具体代码,供大家参考,具体内容如下 通过图像灰度线性变换提高图像对比度和亮度,原图像为src,目标图像为dst,则dst(x,y) = * src(x,y) + . 不仅对单通道图像可以做灰度线性变换,对三通道图像同样可以. #include<opencv2/opencv.hpp>; #include<iostream> using namespace cv; using namespace std; int main(int

  • OpenCV图像几何变换之透视变换

    本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下 1. 基本原理 透视变换(Perspective Transformation)的本质是将图像投影到一个新的视平面,其通用变换公式为: (u,v)为原始图像像素坐标,(x=x'/w',y=y'/w')为变换之后的图像像素坐标.透视变换矩阵图解如下: 仿射变换(Affine Transformation)可以理解为透视变换的特殊形式.透视变换的数学表达式为: 所以,给定透视变换对应的四对像素点坐标,即可求得透视变

  • opencv实现图像几何变换

    本文实例为大家分享了opencv实现图像几何变换的具体代码,供大家参考,具体内容如下 图像伸缩(cv2.resize) 图像的扩大与缩小有专门的一个函数,cv2.resize(),那么关于伸缩需要确定的就是缩放比例,可以是x与y方向相同倍数,也可以单独设置x与y的缩放比例.另外一个就是在缩放以后图像必然就会变化,这就又涉及到一个插值问题.那么这个函数中,缩放有几种不同的插值(interpolation)方法,在缩小时推荐cv2.INTER_ARER,扩大是推荐cv2.INTER_CUBIC和cv

  • OpenCV实现图像距离变换

    图像中两个像素之间的距离有多种定义方式,图像处理中常用的距离有欧式距离.街区距离和棋盘距离 欧式距离 略 街区距离 两个像素点X方向和Y方向的距离之和.欧式距离表示的是从一个像素点到另一个像素点的最短距离,然而有时我们并不能以两个点之间连线的方向前进,例如在一个城市内两点之间的连线可能存在障碍物的阻碍,因此从一个点到另一个点需要沿着街道行走,因此这种距离的度量方式被称为街区距离.街区距离就是由一个像素点到另一个像素点需要沿着X方向和Y方向一共行走的距离,数学表示形式如式所示. 棋盘距离 两个像素

  • OpenCV基于距离变换和分水岭实现图像分割

    目录 一.图像分割 二.基于距离变换和分水岭的图像分割 代码实现 图像处理效果 一.图像分割 图像分割是根据灰度.颜色.纹理和形状等特征,把图像分成若干个特定的.具有独特性质的区域,这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性,并提出感兴趣目标的技术和过程. 它是由图像处理到图像分析的关键步骤.从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程.图像分割的过程也是一个标记过程,即把属于同一区域的像索赋予相同的编号. 其目的是将图像中像素根据一定的规则分为若干(N

  • python opencv 图像尺寸变换方法

    利用Python OpenCV中的 cv.Resize(源,目标,变换方法)就可以实现变换为想要的尺寸了 源文件:就不用说了 目标:你可以对图像进行倍数的放大和缩小 也可以直接的输入尺寸大小 变换的方法: CV_INTER_NN - 最近邻插值, CV_INTER_LINEAR - 双线性插值 (缺省使用) CV_INTER_AREA - 使用象素关系重采样.当图像缩小时候,该方法可以避免波纹出现.当图像放大时,类似于 CV_INTER_NN 方法.. CV_INTER_CUBIC - 立方插值

  • Python OpenCV图像颜色变换示例

    目录 给图像添加颜色 图像按位操作 图像的通道操作 给图像添加颜色 在使用OpenCV操作图像时,有时候需要给图像添加不同的颜色,以达到不同的风格效果.这里介绍的主要是opencv中的cv.applyColorMap()函数. 给图像应用颜色函数cv.applyColorMap(src, colormap, dst=None)src:表示传入的原图:colormap:颜色图类型(17种).可以单独使用,也可以以一个列表的形式批量使用. 以下图举例实现: 直接上代码: # -*-coding:ut

  • Python使用Opencv实现图像特征检测与匹配的方法

    特征检测是计算机对一张图像中最为明显的特征进行识别检测并将其勾画出来.大多数特征检测都会涉及图像的角点.边和斑点的识别.或者是物体的对称轴. 角点检测 是由Opencv的cornerHarris函数实现,其他函数参数说明如下: cv2.cornerHarris(src=gray, blockSize=9, ksize=23, k=0.04) # cornerHarris参数: # src - 数据类型为 float32 的输入图像. # blockSize - 角点检测中要考虑的领域大小. #

  • Python+OpenCV实现图像的全景拼接

    本文实例为大家分享了Python+OpenCV实现图像的全景拼接的具体代码,供大家参考,具体内容如下 环境:python3.5.2 + openCV3.4 1.算法目的 将两张相同场景的场景图片进行全景拼接. 2.算法步骤 本算法基本步骤有以下几步: 步骤1:将图形先进行桶形矫正 没有进行桶形变换的图片效果可能会像以下这样: 图片越多拼接可能就会越夸张. 本算法是将图片进行桶形矫正.目的就是来缩减透视变换(Homography)之后图片产生的变形,从而使拼接图片变得畸形. 步骤2:特征点匹配 本

  • 详解基于python的图像Gabor变换及特征提取

    1.前言 在深度学习出来之前,图像识别领域北有"Gabor帮主",南有"SIFT慕容小哥".目前,深度学习技术可以利用CNN网络和大数据样本搞事情,从而取替"Gabor帮主"和"SIFT慕容小哥"的江湖地位.但,在没有大数据和算力支撑的"乡村小镇"地带,或是对付"刁民小辈","Gabor帮主"可以大显身手,具有不可撼动的地位.IT武林中,有基于C++和OpenCV,或

  • Python OpenCV实现图像傅里叶变换

    目录 二维离散傅里叶变换(DFT) OpenCV 实现图像傅里叶变换(cv.dft) 示例代码 二维离散傅里叶变换(DFT) 对于二维图像处理,通常使用 x , y x, yx,y 表示离散的空间域坐标变量,用 u , v u,vu,v 表示离散的频率域变量.二维离散傅里叶变换(DFT)和反变换(IDFT)为: 二维离散傅里叶变换也可以用极坐标表示: 傅里叶频谱(Fourier spectrum)为: 傅里叶相位谱(Fourier phase spectrum)为: 傅里叶功率谱(Fourier

  • java图像处理之倒角距离变换

    图像处理中的倒角距离变换(Chamfer Distance Transform)在对象匹配识别中经常用到,算法基本上是基于3x3的窗口来生成每个像素的距离值,分为两步完成距离变换,第一步从左上角开始,从左向右.从上到下移动窗口扫描每个像素,检测在中心像素x的周围0.1.2.3四个像素,保存最小距离与位置作为结果,图示如下: 第二步从底向上.从右向左,对每个像素,检测相邻像素4.5.6.7保存最小距离与位置作为结果,如图示所: 完成这两步以后,得到的结果输出即为倒角距离变换的结果.完整的图像倒角距

  • Python在OpenCV里实现极坐标变换功能

    在中学里学习过直角坐标系,也叫做笛卡尔坐标系,它是正交坐标系,不过也学习过极坐标系,这种坐标系比较适合大炮发射的场合.极坐标系的定义如下: 在 平面内取一个定点O, 叫极点,引一条射线Ox,叫做极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向).对于平面内任何一点M,用ρ表示线段OM的长度,θ表示从Ox到OM的角度,ρ叫做点M的极径,θ叫做点M的极角,有序数对 (ρ,θ)就叫点M的极坐标,这样建立的坐标系叫做极坐标系. 极坐标很方便应用到雷达上面,因为雷达不断地转动,反射回来的波计算出距

随机推荐