OpenCV学习三十五:distanceTransform 距离变换函数 您所在的位置:网站首页 minmax函数详解 OpenCV学习三十五:distanceTransform 距离变换函数

OpenCV学习三十五:distanceTransform 距离变换函数

2024-06-02 03:24| 来源: 网络整理| 查看: 265

1. API

该函数有两个初始化API

C++: void distanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize) C++: void distanceTransform( InputArray src, OutputArray dst, OutputArray labels, int distanceType, int maskSize, int labelType=DIST_LABEL_CCOMP ) 2. 参数说明 src – 8-bit, 单通道(二值化)输入图片。dst – 输出结果中包含计算的距离,这是一个32-bit  float 单通道的Mat类型数组,大小与输入图片相同。distanceType – 计算距离的类型那个,可以是 CV_DIST_L1、CV_DIST_L2 、CV_DIST_C。maskSize – 距离变换掩码矩阵的大小,可以是 3(CV_DIST_L1、 CV_DIST_L2 、CV_DIST_C)5(CV_DIST_L2 )CV_DIST_MASK_PRECISE (这个只能在4参数的API中使用) labels – 可选的2D标签输出(离散 Voronoi 图),类型为 CV_32SC1 大小同输入图片。labelType – 输出标签的类型,这里有些两种。 labelType==DIST_LABEL_CCOMP 将周围较近的白色像素点作为一个整体计算其到黑色边缘的距离labelType==DIST_LABEL_PIXEL 单独计算每个白色像素点到其黑色边缘的距离. distanceType参数说明 distanceTypemaskSizea \ b \ c     CV_DIST_C3(3X3)a = 1, b = 1CV_DIST_L13(3X3)a = 1, b = 2CV_DIST_L23(3X3)a=0.955, b=1.3693CV_DIST_L25(5X5)a=1, b=1.4, c=2.1969

其中 a b c 含义:在这个函数中计算每个白色像素到黑色像素(0值像素)的最短距离,因此需要通过最短的移动方式找到这个点兵计算他们之间的值。通常来说移动有水平方向、竖直方向、对角方向、跳跃式几个移动方法。虽然计算距离的方法都是一些很基础的公式,但是这个这个掩码矩阵必须是对阵的(这里插一句,要求对是式为了卷积计算的过程可以使用加速算法),因此掩码矩阵上所有水平和竖直方向的变化量(原文是must have the same shift cost ),这里用 a 代表;对角方向的变化量用 b 代表;跳跃移动的变化量用 c 代表。CV_DIST_C、CV_DIST_L1、CV_DIST_L2(maskSize=5)的计算结果是精确的,CV_DIST_L2(maskSize=3)是一个快速计算方法。

3. 代码

我写的代码结果不明显

#include #include using namespace cv; using namespace std; int main(int argc, char* argv[]){ Mat src = imread("10.jpg"); resize(src, src, Size(), 0.25, 0.25, 1); imshow("src", src); Mat bin; cvtColor(src, bin, CV_BGR2GRAY); threshold(bin, bin, 80, 255, CV_THRESH_BINARY); imshow("bin", bin); Mat Dist, Labels; distanceTransform(bin, Dist, CV_DIST_L1, 3); normalize(Dist, Dist, 0, 1, NORM_MINMAX); imshow("dist1", Dist); distanceTransform(bin, Dist, Labels, CV_DIST_L1, 3, DIST_LABEL_CCOMP); normalize(Dist, Dist, 0, 1, NORM_MINMAX); imshow("dist2", Dist); imshow("labels2", Labels); distanceTransform(bin, Dist, Labels, CV_DIST_L1, 3, DIST_LABEL_PIXEL); normalize(Dist, Dist, 0, 1, NORM_MINMAX); //normalize(Labels, Labels, 0, 255, NORM_MINMAX); imshow("dist3", Dist); imshow("labels3", Labels); waitKey(); return 0; }

后来又找来OpenCV官方的示例代码:

#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include using namespace cv; int maskSize0 = CV_DIST_MASK_5; int voronoiType = -1; int edgeThresh = 100; int distType0 = CV_DIST_L1; // The output and temporary images Mat gray; // threshold trackbar callback static void onTrackbar( int, void* ) { static const Scalar colors[] = { Scalar(0,0,0), Scalar(255,0,0), Scalar(255,128,0), Scalar(255,255,0), Scalar(0,255,0), Scalar(0,128,255), Scalar(0,255,255), Scalar(0,0,255), Scalar(255,0,255) }; int maskSize = voronoiType >= 0 ? CV_DIST_MASK_5 : maskSize0; int distType = voronoiType >= 0 ? CV_DIST_L2 : distType0; Mat edge = gray >= edgeThresh, dist, labels, dist8u; if( voronoiType < 0 ) distanceTransform( edge, dist, distType, maskSize ); else distanceTransform( edge, dist, labels, distType, maskSize, voronoiType ); if( voronoiType < 0 ) { // begin "painting" the distance transform result dist *= 5000; pow(dist, 0.5, dist); Mat dist32s, dist8u1, dist8u2; dist.convertTo(dist32s, CV_32S, 1, 0.5); dist32s &= Scalar::all(255); dist32s.convertTo(dist8u1, CV_8U, 1, 0); dist32s *= -1; dist32s += Scalar::all(255); dist32s.convertTo(dist8u2, CV_8U); Mat planes[] = {dist8u1, dist8u2, dist8u2}; merge(planes, 3, dist8u); } else { dist8u.create(labels.size(), CV_8UC3); for( int i = 0; i < labels.rows; i++ ) { const int* ll = (const int*)labels.ptr(i); const float* dd = (const float*)dist.ptr(i); uchar* d = (uchar*)dist8u.ptr(i); for( int j = 0; j < labels.cols; j++ ) { int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1; float scale = 1.f/(1 + dd[j]*dd[j]*0.0004f); int b = cvRound(colors[idx][0]*scale); int g = cvRound(colors[idx][1]*scale); int r = cvRound(colors[idx][2]*scale); d[j*3] = (uchar)b; d[j*3+1] = (uchar)g; d[j*3+2] = (uchar)r; } } } imshow("Distance Map", dist8u ); } static void help() { printf("\nProgram to demonstrate the use of the distance transform function between edge images.\n" "Usage:\n" "./distrans [image_name -- default image is stuff.jpg]\n" "\nHot keys: \n" "\tESC - quit the program\n" "\tC - use C/Inf metric\n" "\tL1 - use L1 metric\n" "\tL2 - use L2 metric\n" "\t3 - use 3x3 mask\n" "\t5 - use 5x5 mask\n" "\t0 - use precise distance transform\n" "\tv - switch to Voronoi diagram mode\n" "\tp - switch to pixel-based Voronoi diagram mode\n" "\tSPACE - loop through all the modes\n\n"); } const char* keys = { "{1| |stuff.jpg|input image file}" }; int main( int argc, const char** argv ) { help(); CommandLineParser parser(argc, argv, keys); string filename = parser.get("1"); //gray = imread("stuff.jpg", 0); gray = imread("10.jpg", 0); resize(gray, gray, Size(), 0.25, 0.25, 1); if(gray.empty()) { printf("Cannot read image file: %s\n", filename.c_str()); help(); return -1; } namedWindow("Distance Map", 1); createTrackbar("Brightness Threshold", "Distance Map", &edgeThresh, 255, onTrackbar, 0); for(;;) { // Call to update the view onTrackbar(0, 0); int c = waitKey(0) & 255; if( c == 27 ) break; if( c == 'c' || c == 'C' || c == '1' || c == '2' || c == '3' || c == '5' || c == '0' ) voronoiType = -1; if( c == 'c' || c == 'C' ) distType0 = CV_DIST_C; else if( c == '1' ) distType0 = CV_DIST_L1; else if( c == '2' ) distType0 = CV_DIST_L2; else if( c == '3' ) maskSize0 = CV_DIST_MASK_3; else if( c == '5' ) maskSize0 = CV_DIST_MASK_5; else if( c == '0' ) maskSize0 = CV_DIST_MASK_PRECISE; else if( c == 'v' ) voronoiType = 0; else if( c == 'p' ) voronoiType = 1; else if( c == ' ' ) { if( voronoiType == 0 ) voronoiType = 1; else if( voronoiType == 1 ) { voronoiType = -1; maskSize0 = CV_DIST_MASK_3; distType0 = CV_DIST_C; } else if( distType0 == CV_DIST_C ) distType0 = CV_DIST_L1; else if( distType0 == CV_DIST_L1 ) distType0 = CV_DIST_L2; else if( maskSize0 == CV_DIST_MASK_3 ) maskSize0 = CV_DIST_MASK_5; else if( maskSize0 == CV_DIST_MASK_5 ) maskSize0 = CV_DIST_MASK_PRECISE; else if( maskSize0 == CV_DIST_MASK_PRECISE ) voronoiType = 0; } } return 0; } 我的测试图片 OpenCV官方的测试图片

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有