You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# AForge BlobCounter形状检测索引越界异常修复方案

AForge BlobCounter形状检测索引越界异常修复

运行基于AForge库BlobCounter组件编写的形状检测代码,尝试统计物体边缘像素总数时,在shapeChecker.IsConvexPolygon(edgePoints, out corners)行抛出异常:

System.ArgumentOutOfRangeException: 'Index was out of range. It must not be a negative value and must be smaller than the size of the collection.'


异常原因
  • Blob过滤阈值设置不合理:MinWidth=1、MinHeight=1、MaxWidth=8、MaxHeight=8的配置会筛选出大量尺寸极小的噪点Blob,这类Blob提取出的边缘点数量不足3个。IsConvexPolygon方法要求传入的边缘点集合至少包含3个有效点才能构成多边形,点数量不足时内部访问集合索引就会触发越界。
  • 锁位操作存在错误:第一次调用LockBits锁定BmpData1后未做任何操作就直接解锁,属于冗余代码;灰度、阈值处理后生成的是8位灰度图,第二次锁位时错误指定PixelFormat.Format24bppRgb格式,会导致内存读取错位,提取的边缘点数据异常。
  • 缺少入参校验:未对提取到的边缘点集合做有效性判断,直接传入形状检测方法,空集合或点数量不足的集合会直接触发内部逻辑错误。
  • 冗余的颜色过滤操作:阈值处理后已经得到二值图,再调用RGB三通道颜色过滤属于无效操作,还可能破坏已经处理好的二值数据。

修复方案
  1. 调整Blob过滤阈值,过滤过小噪点,修正锁位时的像素格式参数,删除冗余的无效锁位、颜色过滤代码。
  2. 在调用形状检测方法前增加边缘点、角点的数量校验,点数量不足3个无法构成多边形,直接跳过当前Blob避免越界。
  3. 若需要统计物体边缘像素总数,直接读取edgePoints.Count属性即可,该集合存储的就是BlobCounter提取的所有边缘像素坐标。

修改后的核心代码如下:

private void button2_Click(object sender, EventArgs e)
{
    Bitmap bmp = new Bitmap(pictureBox1.Image);
    // 删除冗余的第一次无效LockBits操作
    Grayscale gfilter = new Grayscale(0.2125, 0.7154, 0.0721);
    Invert ifilter = new Invert();
    BradleyLocalThresholding thfilter = new BradleyLocalThresholding();
    bmp = gfilter.Apply(bmp);
    thfilter.ApplyInPlace(bmp);
    ifilter.ApplyInPlace(bmp);

    // 8位灰度图锁位需指定匹配的像素格式,不能使用24位RGB格式
    BitmapData BmpData2 = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

    BlobCounterBase blobCounter = new BlobCounter();
    blobCounter.FilterBlobs = true;
    // 调整Blob尺寸阈值过滤噪点,可根据实际检测目标大小调整数值
    blobCounter.MinWidth = 10;
    blobCounter.MinHeight = 10;
    blobCounter.MaxWidth = bmp.Width;
    blobCounter.MaxHeight = bmp.Height;

    // 二值化后无需做RGB通道颜色过滤,删除冗余ColorFilter逻辑
    blobCounter.ProcessImage(BmpData2);
    bmp.UnlockBits(BmpData2);
    Blob[] blobs = blobCounter.GetObjectsInformation();
    SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
    Bitmap bmp3 = new Bitmap(bmp.Width, bmp.Height);
    Graphics g = Graphics.FromImage(bmp3);
    Pen redPen = new Pen(Color.Red, 2);     
    Pen brownPen = new Pen(Color.Brown, 2);  
    Pen greenPen = new Pen(Color.Green, 2);   
    Pen bluePen = new Pen(Color.Blue, 2);    
    for (int i = 0; i < blobs.Length; i++)
    {
        List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
        // 新增前置校验:边缘点不足3个无法构成多边形,直接跳过
        if (edgePoints == null || edgePoints.Count < 3)
        {
            continue;
        }
        List<IntPoint> corners;
        if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
        {
            // 校验角点数量,避免后续绘制多边形出错
            if (corners == null || corners.Count < 3)
            {
                continue;
            }
            PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners);
            Pen pen;
            if (subType == PolygonSubType.Unknown)
            {
                pen = (corners.Count == 4) ? redPen : bluePen;
            }
            else
            {
                pen = (corners.Count == 4) ? brownPen : greenPen;
            }
            g.DrawPolygon(pen, ToPointsArray(corners));
        }
    }

    redPen.Dispose();
    greenPen.Dispose();
    bluePen.Dispose();
    brownPen.Dispose();
    g.Dispose();

    Clipboard.SetDataObject(bmp3);
    pictureBox1.Image = bmp3;
}

内容的提问来源于stack exchange,提问作者stck_w

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 03:45:34