加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

OpenCV3.0 Examples学习笔记(5)-distrans.cpp

发布时间:2020-12-13 21:21:06 所属栏目:PHP教程 来源:网络整理
导读:这个系列的目的是通过对OpenCV示例,进1步了解OpenCV函数的使用,不触及具体原理。 目录 简介 Example运行截图 Example分析 Example代码 简介 本文记录了对OpenCV示例 distrans .cpp 的分析。 资料地址: http://docs.opencv.org/3.0.0/d4/d11/distrans_8cpp-
这个系列的目的是通过对OpenCV示例,进1步了解OpenCV函数的使用,不触及具体原理。

目录
简介
Example运行截图
Example分析
Example代码

简介
本文记录了对OpenCV示例distrans.cpp的分析。
资料地址:http://docs.opencv.org/3.0.0/d4/d11/distrans_8cpp-example.html

首先这个示例,主要讲述了distanceTransform函数的使用。distanceTransform函数用于计算2值图象中所有像素力其最近的值为0像素的近似距离。这个函数非常有用,
可以用于细化轮廓或寻觅物体质心。
全部示例可以总结为
(1)2值化
(2)调用distanceTransform函数
(3)根据distanceTransform函数计算结果,绘制距离变换图象(图象的值表示距离)。


Example截图
原图
处理结果
参数

2值化阈值:edgeThresh=100
distanceTransform参数:
distanceType = DIST_L1
maskSize = DIST_MASK_5


Example分析
示例主要触及distanceTransform函数的使用。
如果对distanceTransform算法本身感兴趣可以传送至Distance Transform  距离变换。
如果想进1步了解distanceTransform函数的使用,可以传送至Opencv距离变换distanceTransform利用——细化字符轮廓&&查找物体质心。
distanceTransform
计算2值图象,任意点到最近背景点的距离,1般为非零点到最近零点的距离。

distanceTransform函数计算2值图象中所有像素力其最近的值为0像素的近似距离。明显如果像素本身为0,则其距离明显也为0。

函数原型:
void distanceTransform( InputArray src, OutputArray dst,
                                     int distanceType, int maskSize, int dstType=CV_32F);
参数说明:
src:源图象,需要采取2值化后的8位灰度图象
dst:目标图象,可以是8位或32位浮点,尺寸和src相同
distanceType:计算距离的方式,具体以下
    DIST_USER    = ⑴,  //!< User defined distance
    DIST_L1      = 1,   //!< distance = |x1-x2| + |y1-y2|
    DIST_L2      = 2,   //!< the simple euclidean distance
    DIST_C       = 3,   //!< distance = max(|x1-x2|,|y1-y2|)
    DIST_L12     = 4,   //!< L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1))
    DIST_FAIR    = 5,   //!< distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998
    DIST_WELSCH  = 6,   //!< distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846
    DIST_HUBER   = 7    //!< distance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345
maskSize:掩膜的尺寸,具体以下:
    DIST_MASK_3       = 3, //!< mask=3
    DIST_MASK_5       = 5, //!< mask=5
    DIST_MASK_PRECISE = 0  //!<
    PS:当distanceType = DIST_L1或DIST_C时,maskSize强迫为3(设为5也没用)
dstType:目标图象的类型,默许为CV_32F;

Example代码

#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

#include <stdio.h>

using namespace std;
using namespace cv;

int maskSize0 = DIST_MASK_5;
int voronoiType = ⑴;
int edgeThresh = 100;
int distType0 = DIST_L1;

// The output and temporary images
Mat gray;

// threshold trackbar callback
static void onTrackbar( int,void* )
{
    static const Scalar colors[] =
    {
        Scalar(0,0),Scalar(255,128,Scalar(0,255),255)
    };

    int maskSize = voronoiType >= 0 ? DIST_MASK_5 : maskSize0;
    int distType = voronoiType >= 0 ? DIST_L2 : distType0;

    Mat edge = gray >= edgeThresh,dist,labels,dist8u;

    if( voronoiType < 0 )
        distanceTransform( edge,distType,maskSize );
    else
        distanceTransform( edge,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,0);
        dist32s *= ⑴;

        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]⑴)%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 ../data/stuff.jpg]n"
            "nHot keys: n"
            "tESC - quit the programn"
            "tC - use C/Inf metricn"
            "tL1 - use L1 metricn"
            "tL2 - use L2 metricn"
            "t3 - use 3x3 maskn"
            "t5 - use 5x5 maskn"
            "t0 - use precise distance transformn"
            "tv - switch to Voronoi diagram moden"
            "tp - switch to pixel-based Voronoi diagram moden"
            "tSPACE - loop through all the modesnn");
}

const char* keys =
{
    "{@image |../data/stuff.jpg|input image file}"
};

int main( int argc,const char** argv )
{
    help();
    CommandLineParser parser(argc,argv,keys);
    string filename = parser.get<string>(0);
    gray = imread(filename.c_str(),0);
    if(gray.empty())
    {
        printf("Cannot read image file: %sn",filename.c_str());
        help();
        return ⑴;
    }

    namedWindow("Distance Map",1);
    createTrackbar("Brightness Threshold","Distance Map",&edgeThresh,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 = ⑴;

        if( c == 'c' || c == 'C' )
            distType0 = DIST_C;
        else if( c == '1' )
            distType0 = DIST_L1;
        else if( c == '2' )
            distType0 = DIST_L2;
        else if( c == '3' )
            maskSize0 = DIST_MASK_3;
        else if( c == '5' )
            maskSize0 = DIST_MASK_5;
        else if( c == '0' )
            maskSize0 = 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 = ⑴;
                maskSize0 = DIST_MASK_3;
                distType0 = DIST_C;
            }
            else if( distType0 == DIST_C )
                distType0 = DIST_L1;
            else if( distType0 == DIST_L1 )
                distType0 = DIST_L2;
            else if( maskSize0 == DIST_MASK_3 )
                maskSize0 = DIST_MASK_5;
            else if( maskSize0 == DIST_MASK_5 )
                maskSize0 = DIST_MASK_PRECISE;
            else if( maskSize0 == DIST_MASK_PRECISE )
                voronoiType = 0;
        }
    }

    return 0;
}

参考资料:
1.《基于distanceTransform-距离变换的区域中心提取
2.《Distance Transform 距离变换
3.《Distance Transform  距离变换
4.《Opencv距离变换distanceTransform利用——细化字符轮廓&&查找物体质心
5.《基于距离变换的新型骨架提取方法


(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读