以下是完整的 ClipContoursXLD
函数实现,完全复现 Halcon 的 clip_contours_xld
算子功能,包含高性能优化和详尽注释,兼容 C# 7.3:
using System;
using System.Collections.Generic;
using System.Linq;
using OpenCvSharp;
/// <summary>
/// 完全复现Halcon的clip_contours_xld算子
/// 功能:按矩形区域裁剪轮廓(支持部分可见轮廓的保留)
/// 性能:采用扫描线算法+边界交叉检测,时间复杂度O(n)
/// 兼容性:C# 7.3 / OpenCvSharp 4.x
/// </summary>
public static class HalconContourClipper
{
/// <summary>
/// 轮廓点结构(优化内存布局)
/// </summary>
public struct ContourPoint
{
public float X;
public float Y;
public ContourPoint(float x, float y) => (X, Y) = (x, y);
}
/// <summary>
/// 主裁剪函数(参数顺序与Halcon完全一致)
/// </summary>
/// <param name="contours">输入轮廓(支持多段轮廓)</param>
/// <param name="row1">矩形区域左上角Y坐标</param>
/// <param name="column1">矩形区域左上角X坐标</param>
/// <param name="row2">矩形区域右下角Y坐标</param>
/// <param name="row2">矩形区域右下角X坐标</param>
/// <returns>裁剪后的轮廓集合</returns>
public static IEnumerable<IEnumerable<Point2f>> ClipContoursXld(
IEnumerable<IEnumerable<Point2f>> contours,
double row1, double column1,
double row2, double column2)
{
// === 参数校验 ===
if (contours == null) throw new ArgumentNullException();
if (row1 > row2) (row1, row2) = (row2, row1);
if (column1 > column2) (column1, column2) = (column2, column1);
// === 预处理坐标(转为float减少计算量)===
float yMin = (float)row1, yMax = (float)row2;
float xMin = (float)column1, xMax = (float)column2;
// === 核心裁剪逻辑 ===
foreach (var contour in contours)
{
var clipped = ClipSingleContour(contour?.ToList(), yMin, xMin, yMax, xMax);
if (clipped != null && clipped.Count > 0)
yield return clipped;
}
}
#region 核心裁剪算法
/// <summary>
/// 单条轮廓裁剪(采用Bresenham扫描线算法优化)
/// </summary>
private static List<Point2f> ClipSingleContour(
List<Point2f> contour,
float yMin, float xMin,
float yMax, float xMax)
{
if (contour == null || contour.Count < 2)
return null;
var result = new List<Point2f>(contour.Count);
Point2f? lastPoint = null;
bool lastInside