OpencvSharp 算子学习教案之 - Cv2.ConvexHullIndices 重载1大家好Opencv在很多工程项目中都会用到而OpencvSharp则是以C#开发与实现的Opencv操作库对.NET开发人员友好但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案供大家参考学习。Cv2.ConvexHullIndices教案版本V1.0面向对象OpenCvSharp 初学者所属模块imgproc源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs:3619 / 3642摘要本页演示ConvexHullIndices(IEnumerablePoint)如何返回凸包在原始点集中的索引并说明这些索引为什么常用于后续的缺陷分析。1. 函数名称带参数签名publicstaticint[]ConvexHullIndices(IEnumerablePointpoints,boolclockwisefalse)2. 函数用途Cv2.ConvexHullIndices(...)用来求一组点的凸包索引。这个重载最适合整数点集输入可以直接是Point[]。返回结果是 0-based 索引数组。非常适合后续回查原始点坐标。它常用于先求凸包索引再做ConvexityDefects。把索引映射回原始轮廓点。需要知道“凸包对应哪些原始点”的教学场景。轮廓分析的中间步骤。3. 函数公式可以把这个结果理解为h i ConvexHullIndices ⁡ ( P ) i , p i P [ h i ] h_i \operatorname{ConvexHullIndices}(P)_i, \quad p_i P[h_i]hi​ConvexHullIndices(P)i​,pi​P[hi​]其中P PP是原始点集h i h_ihi​是凸包第i ii个顶点在原始点集中的索引p i p_ipi​是映射回来的点。4. 函数原理说明这个函数和ConvexHull(...)的区别只有一个输出不是点而是点的编号。对初学者来说最重要的是索引本身不能直接画图。你必须用索引去原始点集中取值。这些索引通常是ConvexityDefects的前置输入。这也是为什么它在教学里特别值得单独拿出来讲。5. 参数含义解析参数名类型必填含义pointsIEnumerable是输入整数点集clockwisebool否输出索引对应的点序是否按顺时针排列补充说明索引是 0-based 的。需要点坐标时直接用points[index]取回。如果后面要做缺陷分析这个结果通常比点集更关键。6. 应用场景列表场景名场景说明典型用途场景A索引回查通过索引找回原始点轮廓分析场景B缺陷分析作为 ConvexityDefects 的输入手势/形状识别场景C高亮显示把索引对应的点高亮出来可视化场景D教学入门理解“索引不是坐标”OpenCvSharp 入门7. 函数使用示例与 WPF 场景一一对应说明下面示例对应 WPF 场景 A。它把凸包索引和原始轮廓中的点一一对应起来。usingSystem;usingSystem.Globalization;usingOpenCvSharp;internalstaticclassProgram{privatestaticvoidMain(){// 这组整数点故意带有凹口方便读者观察索引是如何指向外层凸包点的。Point[]contourPoints{newPoint(92,232),newPoint(118,126),newPoint(146,88),newPoint(164,146),newPoint(190,72),newPoint(216,148),newPoint(242,92),newPoint(268,126),newPoint(300,232),newPoint(300,252),newPoint(92,252),};// 这里返回的是原始点集中的索引而不是坐标本身。int[]hullIndicesCv2.ConvexHullIndices(contourPoints,clockwise:false);for(varindex0;indexhullIndices.Length;index){varpointIndexhullIndices[index];varpointcontourPoints[pointIndex];Console.WriteLine($HullIndex{index1}{pointIndex}, Point ({point.X},{point.Y}));}varcontourFloatToPoint2fArray(contourPoints);varhullPointsSelectPointsByIndices(contourFloat,hullIndices);Console.WriteLine($ContourCount {contourPoints.Length});Console.WriteLine($HullIndexCount {hullIndices.Length});Console.WriteLine($ContourArea {Math.Abs(Cv2.ContourArea(contourFloat)).ToString(F2,CultureInfo.InvariantCulture)});Console.WriteLine($HullArea {Math.Abs(Cv2.ContourArea(hullPoints)).ToString(F2,CultureInfo.InvariantCulture)});Console.WriteLine($HullPerimeter {Cv2.ArcLength(hullPoints,true).ToString(F2,CultureInfo.InvariantCulture)});Console.WriteLine($HullIsConvex {Cv2.IsContourConvex(hullPoints)});// 这一行是本例的核心索引是给原始轮廓用的取回去后才能继续画图或做分析。Console.WriteLine(ConvexHullIndices 的结果可以直接反查回原始点坐标。\n);}privatestaticPoint2f[]ToPoint2fArray(Point[]points){varfloatPointsnewPoint2f[points.Length];for(varindex0;indexpoints.Length;index){floatPoints[index]newPoint2f(points[index].X,points[index].Y);}returnfloatPoints;}}8. 常见错误与避坑误把索引当作坐标直接绘图。忘记索引是 0-based。没有先保留原始轮廓导致无法反查点坐标。把ConvexHullIndices和ConvexHull的返回值混淆。9. 进阶扩展可以把索引与原始点一起显示在图上。可以把索引直接传给ConvexityDefects。可以和凸包点图叠加观察索引和坐标的对应关系。可以比较Point和Point2f两种输入的索引结果。10. 小结Cv2.ConvexHullIndices(...)的IEnumerablePoint重载返回的是点编号不是点坐标。一旦理解这一点后面的ConvexityDefects就会非常顺手。11. 相关链接WPF 教学控件Cv2ConvexHullIndicesControl.xaml.cs样例实现ConvexHullIndicesPointEnumerableSample.cs官方文档源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs另一个重载源码位置OpenCvSharp/Cv2/Cv2_imgproc.cs