OpencvSharp 算子学习教案之 - Cv2.MatchShapes 重载2
OpencvSharp 算子学习教案之 - Cv2.MatchShapes 重载2大家好Opencv在很多工程项目中都会用到而OpencvSharp则是以C#开发与实现的Opencv操作库对.NET开发人员友好但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案供大家参考学习。Cv2.MatchShapes教案版本V1.0面向对象OpenCvSharp 初学者所属模块imgproc源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs:3491 / 3514摘要本页演示MatchShapes(IEnumerablePoint, IEnumerablePoint, ShapeMatchModes, double)如何直接比较两个整数点集的形状相似度并说明分数越小越相似。1. 函数名称带参数签名publicstaticdoubleMatchShapes(IEnumerablePointcontour1,IEnumerablePointcontour2,ShapeMatchModesmethod,doubleparameter0)2. 函数用途Cv2.MatchShapes(...)用来比较两个轮廓的形状相似度。这个重载最适合整数点集直接参与比较的场景输入可以直接是Point[]或其它整数点序列。不需要先包装成Mat。返回值越小两个轮廓越相似。它常用于图形识别的候选筛选。轮廓相似度排序。基于外形的简单分类。初学者理解 Hu 矩比较的入门示例。3. 函数公式MatchShapes 的三种方法都基于 Hu 矩。官方定义可以写成m i sign ( h i ) ⋅ log ( h i ) m_i \operatorname{sign}(h_i)\cdot \log(h_i)misign(hi)⋅log(hi)I 1 ( A , B ) ∑ i 1 7 ∣ 1 m i A − 1 m i B ∣ I_1(A,B)\sum_{i1}^{7}\left|\frac{1}{m_i^A}-\frac{1}{m_i^B}\right|I1(A,B)i1∑7miA1−miB1I 2 ( A , B ) ∑ i 1 7 ∣ m i A − m i B ∣ I_2(A,B)\sum_{i1}^{7}\left|m_i^A-m_i^B\right|I2(A,B)i1∑7miA−miBI 3 ( A , B ) max i 1 7 ∣ m i A − m i B ∣ ∣ m i A ∣ I_3(A,B)\max_{i1}^{7}\frac{\left|m_i^A-m_i^B\right|}{\left|m_i^A\right|}I3(A,B)i1max7miAmiA−miB4. 函数原理说明这个重载和 InputArray 版本的数学意义是一样的只是输入容器更直接。对初学者来说最重要的是记住Point[]是最常见的轮廓写法。MatchShapes 比较的是整体形状不是轮廓坐标本身。三种方法的数值不同但“越小越像”这条规则一致。parameter目前仍然是保留参数教学时可以把重点放在method上。5. 参数含义解析参数名类型必填含义contour1IEnumerable是第一个轮廓contour2IEnumerable是第二个轮廓methodShapeMatchModes是形状比较方法parameterdouble否方法相关参数当前未启用补充说明这个重载最适合直接从轮廓列表、数组或集合里取数据。如果你已经有Point[]就不需要再手动包装成Mat。ShapeMatchModes.I1、I2、I3都可以直接使用。6. 应用场景列表场景名场景说明典型用途场景A轮廓筛选直接对整数轮廓做比较目标检测场景B候选排序对多个候选按分数排序识别辅助场景C教学对比与 InputArray 版本对照OpenCvSharp 入门场景D像素级数据直接处理整数坐标轮廓几何分析7. 函数使用示例与 WPF 场景一一对应说明下面示例对应 WPF 场景 B。它直接拿整数点集进行比较并打印三种方法的分数。usingSystem;usingSystem.Globalization;usingOpenCvSharp;internalstaticclassProgram{privatestaticvoidMain(){// 参考轮廓使用整数像素坐标便于初学者直接把它和图片上的像素点对应起来。Point[]referencePoints{newPoint(77,96),newPoint(164,59),newPoint(262,74),newPoint(304,136),newPoint(286,214),newPoint(196,262),newPoint(93,234),newPoint(58,150),};// 候选轮廓保留了“差不多的形状”但和参考轮廓不是完全一样分数会更直观地大于 0。Point[]candidatePoints{newPoint(120,82),newPoint(188,92),newPoint(250,124),newPoint(266,194),newPoint(212,248),newPoint(144,252),newPoint(92,198),newPoint(88,126),};// 直接把整数点集传给 MatchShapes 就可以不需要先转成 Mat。doublescoreI1Cv2.MatchShapes(referencePoints,candidatePoints,ShapeMatchModes.I1);doublescoreI2Cv2.MatchShapes(referencePoints,candidatePoints,ShapeMatchModes.I2);doublescoreI3Cv2.MatchShapes(referencePoints,candidatePoints,ShapeMatchModes.I3);Console.WriteLine($ReferenceCount {referencePoints.Length});Console.WriteLine($CandidateCount {candidatePoints.Length});Console.WriteLine($I1 {scoreI1.ToString(E6,CultureInfo.InvariantCulture)});Console.WriteLine($I2 {scoreI2.ToString(E6,CultureInfo.InvariantCulture)});Console.WriteLine($I3 {scoreI3.ToString(E6,CultureInfo.InvariantCulture)});Console.WriteLine($ReferenceArea {Math.Abs(Cv2.ContourArea(referencePoints)).ToString(F2,CultureInfo.InvariantCulture)});Console.WriteLine($CandidateArea {Math.Abs(Cv2.ContourArea(candidatePoints)).ToString(F2,CultureInfo.InvariantCulture)});// 这一行是本例的核心分数越小两个轮廓越相似。Console.WriteLine(MatchShapes 的结果越接近 0说明两个形状越像。\n);}}8. 常见错误与避坑把 MatchShapes 当成“是否相等”的判断它实际是相似度比较。只看某一个方法的数值不看整体形状差异。忘记parameter当前没有实际作用。误以为整数点集和浮点点集在比较意义上有根本差别实际上它们都在比较轮廓形状。9. 进阶扩展可以对多个候选轮廓批量计算分数然后排序。可以先做轮廓平滑再观察分数是否更稳定。可以把 MatchShapes 和FindContours串起来做分类前筛选。可以和ContourArea、ArcLength一起做综合特征判断。10. 小结Cv2.MatchShapes(...)的IEnumerablePoint重载适合直接用整数轮廓做相似度比较。如果你的输入本来就是像素轮廓这个版本通常最顺手。11. 相关链接WPF 教学控件Cv2MatchShapesControl.xaml.cs样例实现MatchShapesPointEnumerableSample.cs官方文档源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs另一个重载源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs