【Emgu CV教程】10.13、利用形状场景算法比较轮廓

本文介绍了如何使用Emgu.CV中的ShapeContextDistanceExtractor进行轮廓比较,通过实例展示了如何从原始图像中提取轮廓、筛选和比较,以及计算形状场景的距离来衡量相似性。
摘要由CSDN通过智能技术生成


形状场景算法比较轮廓,要引用Emgu.CV.Shape,定义检测器ShapeContextDistanceExtractor,然后对两个轮廓进行比较,得出结果。

一、演示

1.原始素材

原始图像srcMat1如下图:
在这里插入图片描述
待比较的图像srcMat2如下图:
在这里插入图片描述

2.代码

轮廓检索模式要选择RetrType.External,代码如下:

Mat tempMat1 = srcMat1.Clone();
Mat tempMat2 = srcMat2.Clone();
Mat gray1 = new Mat();
Mat gray2 = new Mat();

// 二值化图片1,确保黑里面找白
CvInvoke.CvtColor(tempMat1, gray1, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(gray1, gray1, 50, 255, ThresholdType.Binary);
VectorOfVectorOfPoint contours1 = new VectorOfVectorOfPoint();
VectorOfRect hierarchy1 = new VectorOfRect();
CvInvoke.FindContours(gray1, contours1, hierarchy1, RetrType.External, ChainApproxMethod.ChainApproxNone);
Mat contourMat1 = new Mat(new System.Drawing.Size(gray1.Cols, gray1.Rows), DepthType.Cv8U, 1);
contourMat1.SetTo(new MCvScalar(0, 0, 0));

// 按照面积筛选,太小的轮廓不计算
Dictionary<int, double> dict1 = new Dictionary<int, double>();
if (contours1.Size > 0)
{
    for (int i = 0; i < contours1.Size; i++)
    {
        double area = CvInvoke.ContourArea(contours1[i]);
        Rectangle rect = CvInvoke.BoundingRectangle(contours1[i]);
        if (rect.Width > 2 && rect.Height > 2 && area < 3000000)
        {
            dict1.Add(i, area);
        }
    }
}

// 二值化图片2,确保黑里面找白
CvInvoke.CvtColor(tempMat2, gray2, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(gray2, gray2, 50, 255, ThresholdType.Binary);
VectorOfVectorOfPoint contours2 = new VectorOfVectorOfPoint();
VectorOfRect hierarchy2 = new VectorOfRect();
CvInvoke.FindContours(gray2, contours2, hierarchy2, RetrType.External, ChainApproxMethod.ChainApproxNone);
Mat contourMat2 = new Mat(new System.Drawing.Size(gray1.Cols, gray1.Rows), DepthType.Cv8U, 1);
contourMat2.SetTo(new MCvScalar(0, 0, 0));

// 按照面积筛选,太小的轮廓不计算
Dictionary<int, double> dict2 = new Dictionary<int, double>();
if (contours2.Size > 0)
{
    for (int i = 0; i < contours2.Size; i++)
    {
        double area = CvInvoke.ContourArea(contours2[i]);
        Rectangle rect = CvInvoke.BoundingRectangle(contours2[i]);

        if (rect.Width > 2 && rect.Height > 2 && area < 3000000)
        {
            dict2.Add(i, area);
        }
    }
}

// 排序,取最大的轮廓再判断
IOrderedEnumerable<KeyValuePair<int, double>> descendingDict1 = dict1.OrderByDescending(x => x.Value);
IOrderedEnumerable<KeyValuePair<int, double>> descendingDict2 = dict2.OrderByDescending(x => x.Value);
using (HistogramCostExtractor comparer = new ChiHistogramCostExtractor())
using (ThinPlateSplineShapeTransformer transformer = new ThinPlateSplineShapeTransformer())
using (ShapeContextDistanceExtractor extractor = new ShapeContextDistanceExtractor(comparer, transformer))
{
    CvInvoke.DrawContours(contourMat1, contours1, descendingDict1.First().Key, new MCvScalar(255, 255, 255), 1);
    CvInvoke.DrawContours(contourMat2, contours2, descendingDict2.First().Key, new MCvScalar(255, 255, 255), 1);
    float distance = extractor.ComputeDistance(contours1[descendingDict1.First().Key], contours2[descendingDict2.First().Key]);
    MessageBox.Show("形状场景距离是:" + distance);
}

3.运行结果

利用extractor.ComputeDistance()函数计算出的形状场景距离是:0.1476557

在这里插入图片描述
如果srcMat2采用和srcMat1相同的图形,计算出的形状场景距离是:0.000375
在这里插入图片描述
因此记住它的特点:使用“距离”作为形状比较的度量标准,距离越小相似度越高


原创不易,请勿抄袭。共同进步,相互学习。

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值