• OpenCV计算形状之间的相似度ShapeContextDistanceExtractor类的使用


    • 操作系统:ubuntu22.04
    • OpenCV版本:OpenCV4.9
    • IDE:Visual Studio Code
    • 编程语言:C++11

    1.功能描述

    ShapeContextDistanceExtractor是OpenCV库中的一个类,主要用于计算形状之间的相似度或距离。它是基于形状上下文(Shape Context)特征描述符的,这是一种在计算机视觉和图像处理领域广泛使用的形状匹配技术。该方法由Belongie等人在2000年代初提出,通过分析形状边界点的邻域分布来描述形状特征,进而计算形状间的相似度。

    2.使用场景

    形状匹配:在图像数据库中查找相似的形状或对象。
    物体识别:作为特征提取的一部分,辅助分类或识别任务。
    内容基于的图像检索:根据形状内容搜索图像。

    3.函数computeDistance

    计算由其轮廓定义的两个形状之间的形状距离,首先提取每个轮廓的关键点及其邻域信息,然后通过比较不同轮廓间对应关键点的邻域分布差异来量化形状间的距离。

    3.1函数原型

    
    virtual float cv::ShapeDistanceExtractor::computeDistance	(
    InputArray 	contour1,
    InputArray 	contour2 
    )		
    
    

    3.2 参数

    • 参数contour1 定义第一个形状的轮廓.
    • 参数contour2 定义第二个形状的轮廓…

    4 示例代码

    #include "opencv2/highgui.hpp"
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/imgproc.hpp"
    #include "opencv2/shape.hpp"
    
    #include 
    #include 
    #include 
    using namespace std;
    using namespace cv;
    
    static vector< Point > simpleContour( const Mat& currentQuery, int n = 300 )
    {
        vector< vector< Point > > _contoursQuery;
        vector< Point > contoursQuery;
        findContours( currentQuery, _contoursQuery, RETR_LIST, CHAIN_APPROX_NONE );
        for ( size_t border = 0; border < _contoursQuery.size(); border++ )
        {
            for ( size_t p = 0; p < _contoursQuery[ border ].size(); p++ )
            {
                contoursQuery.push_back( _contoursQuery[ border ][ p ] );
            }
        }
        // In case actual number of points is less than n
        int dummy = 0;
        for ( int add = ( int )contoursQuery.size() - 1; add < n; add++ )
        {
            contoursQuery.push_back( contoursQuery[ dummy++ ] );  // adding dummy values
        }
        // 均匀采样
        cv::randShuffle( contoursQuery );
        vector< Point > cont;
        for ( int i = 0; i < n; i++ )
        {
            cont.push_back( contoursQuery[ i ] );
        }
        return cont;
    }
    int main( int argc, char** argv )
    {
        string path = "/media/dingxin/data/study/OpenCV/sources/images/shape/";
      
        cv::Ptr< cv::ShapeContextDistanceExtractor > mysc = cv::createShapeContextDistanceExtractor();
        Size sz2Sh( 300, 300 );
        stringstream queryName;
        int indexQuery = 1;
        queryName << path << indexQuery << ".jpg";
        Mat query = imread( queryName.str(), IMREAD_GRAYSCALE );
        Mat queryToShow;
        resize( query, queryToShow, sz2Sh, 0, 0, INTER_LINEAR_EXACT );
        imshow( "QUERY", queryToShow );
        moveWindow( "TEST", 0, 0 );
        vector< Point > contQuery = simpleContour( query );
        int bestMatch             = 0;
        float bestDis             = FLT_MAX;
        for ( int ii = 1; ii <= 4; ii++ )
        {
            if ( ii == indexQuery )
                continue;
            waitKey( 30 );
            stringstream iiname;
            iiname << path << ii << ".jpg";
            cout << "name: " << iiname.str() << endl;
            Mat iiIm = imread( iiname.str(), 0 );
            Mat iiToShow;
            resize( iiIm, iiToShow, sz2Sh, 0, 0, INTER_LINEAR_EXACT );
            imshow( "TEST", iiToShow );
            moveWindow( "TEST", sz2Sh.width + 50, 0 );
            vector< Point > contii = simpleContour( iiIm );
            float dis              = mysc->computeDistance( contQuery, contii );
            //获取匹配度最佳的id和匹配距离值
            if ( dis < bestDis )
            {
                bestMatch = ii;
                bestDis   = dis;
            }
            std::cout << " distance between " << queryName.str() << " and " << iiname.str() << " is: " << dis << std::endl;
        }
        destroyWindow( "TEST" );
        stringstream bestname;
        bestname << path << bestMatch << ".jpg";
        Mat iiIm = imread( bestname.str(), 0 );
        Mat bestToShow;
        resize( iiIm, bestToShow, sz2Sh, 0, 0, INTER_LINEAR_EXACT );
        imshow( "BEST MATCH", bestToShow );
        moveWindow( "BEST MATCH", sz2Sh.width + 50, 0 );
        waitKey();
        return 0;
    }
    

    运行结果

    我一共选了4张图,拿第一张图跟其他三张图比较,看哪个图跟第一张图里的足球形状匹配的最好。四张图如下:

    运行结果:
    在这里插入图片描述
    命令行输出结果:
    在这里插入图片描述

  • 相关阅读:
    vue3响应式系统
    QT(1)- QString
    SQL Server如何精准匹配字符中的字符,绝对匹配。
    MATLAB/Python编程 | 图片的形态学处理
    散列表(1)-集合/用位向量实现集合
    中华传统文化题材网页设计主题:基于HTML+CSS设计放飞青春梦想网页【学生网页设计作业源码】
    关于深度学习高维矩阵的形象化理解
    极简idea下git操作(二)
    机器学习1
    苹果15OTG音频转接器方案大卖-无敌成本加兼容性性价比直接拉满
  • 原文地址:https://blog.csdn.net/jndingxin/article/details/139656428