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 <iostream>
#include <opencv2/core/utility.hpp>
#include <string>
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张图,拿第一张图跟其他三张图比较,看哪个图跟第一张图里的足球形状匹配的最好。四张图如下:

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

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用Java和OpenCV计算两张图片的相似度,可以采用以下步骤: 1. 加载图片:使用OpenCV的Java接口,加载两张待比较的图片,可以使用Imgcodecs.imread方法读取图片。 2. 提取特征:使用OpenCV的FeatureDetector和DescriptorExtractor等,对图片进行特征提取和描述。 3. 计算相似度使用OpenCV的DescriptorMatcher,将提取的特征进行匹配,并计算相似度。 下面是一个简单的Java代码示例: ``` import org.opencv.core.*; import org.opencv.features2d.*; import org.opencv.imgcodecs.Imgcodecs; public class ImageMatcher { public static void main(String[] args) { // 加载图片 Mat img1 = Imgcodecs.imread("image1.jpg"); Mat img2 = Imgcodecs.imread("image2.jpg"); // 提取ORB特征 ORB orb = ORB.create(); MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); Mat descriptors1 = new Mat(); Mat descriptors2 = new Mat(); orb.detectAndCompute(img1, new Mat(), keypoints1, descriptors1); orb.detectAndCompute(img2, new Mat(), keypoints2, descriptors2); // 计算相似度 DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); MatOfDMatch matches = new MatOfDMatch(); matcher.match(descriptors1, descriptors2, matches); // 输出相似度 double maxDist = 0; double minDist = 100; DMatch[] matchArray = matches.toArray(); for (int i = 0; i < matchArray.length; i++) { double dist = matchArray[i].distance; if (dist < minDist) minDist = dist; if (dist > maxDist) maxDist = dist; } double similarity = (1 - minDist / maxDist) * 100; System.out.println("相似度:" + similarity + "%"); } } ``` 在这个例子中,我们使用OpenCV的ORB算法进行特征提取,使用了Hamming距离进行特征匹配,计算出了两张图片的相似度。请注意,在实际应用中可能需要根据具体情况选择不同的算法和参数,以获得更准确的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值