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

如何正确使用Graphics处理AForge.IntPoint解决类型转换报错

问题描述

借助AForge的BlobCounter函数实现椭圆对象检测时,调用Graphics类绘制检测结果触发错误,具体报错信息如下:

Argument 2:cannot covert from 'AForge.IntPoint' to 'System.Drawing.PointF'

对应实现代码如下:

namespace blobdnm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog sfd = new OpenFileDialog();
            sfd.Filter = "Image Files|*.bmp|All Files|*.*";
            sfd.InitialDirectory = ".";
            if (sfd.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            pictureBox1.ImageLocation = sfd.FileName;
        }
        private void button2_Click(object sender, EventArgs e)
        {
            Bitmap bmp = new Bitmap(pictureBox1.Image);
            BitmapData BmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            byte[] data = new byte[bmp.Width*bmp.Height*3];
            IntPtr ptr = BmpData.Scan0;
            Marshal.Copy(ptr, data, 0, data.Length);
            for (int i = 0; i < bmp.Width*bmp.Height*3; i=i+3)
            {
                double a = data[i] * 0.2125 + data[i + 1] * 0.7154 + data[i + 2] *0.0721;
                if(a>100)
                {
                    data[i] = 0;
                    data[i+1] = 0;
                    data[i+2] = 0;
                }
            }
            Bitmap bmp2 = new Bitmap(bmp.Width,bmp.Height,PixelFormat.Format24bppRgb);
            BitmapData BmpData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            Marshal.Copy(data, 0,BmpData2.Scan0, data.Length);
            bmp2.UnlockBits(BmpData2);
            ColorFiltering colorFilter = new ColorFiltering();
            BlobCounter blobCounter = new BlobCounter();
            blobCounter.FilterBlobs = true;
            blobCounter.MinWidth = 5;
            blobCounter.MinHeight = 5;
            blobCounter.MaxWidth = 3000;
            blobCounter.MaxHeight = 3000;
            blobCounter.ProcessImage(BmpData2);
            Blob[] blobs = blobCounter.GetObjectsInformation();
            Graphics g = Graphics.FromImage(bmp2);
            Pen redPen = new Pen(Color.Red, 2);
            List<IntPoint> edgePoints=null;
            for (int i = 0; i < blobs.Length; i++)
            {
                 edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                for (int k = 0; k < edgePoints.Count; k++)
                {
                    g.DrawPolygon(redPen, edgePoints[k]);  //报错位置
                }
            }
            redPen.Dispose();
             g.Dispose();
             pictureBox1.Image = bmp2;
         }
         private System.Drawing.Point[] ToPointsArray(List<IntPoint> points)
         {
            System.Drawing.Point[] array = new System.Drawing.Point[points.Count];

             for (int i = 0, n = points.Count; i < n; i++)
             {
                 array[i] = new System.Drawing.Point(points[i].X, points[i].Y);
             }
             return array;
        }
    }
}
错误原因
  • Graphics.DrawPolygon方法的第二个参数要求传入点类型数组(System.Drawing.Point[]或System.Drawing.PointF[]),但代码中循环传入单个AForge.IntPoint对象,参数结构不符合方法要求。
  • AForge自定义的IntPoint类型和System.Drawing命名空间下的Point/PointF不存在隐式转换规则,无法直接作为GDI+绘制方法的参数传入。
  • 代码中已经实现了ToPointsArray类型转换方法,但绘制逻辑中未调用该方法做类型适配。
  • 额外隐患:加载的原图bmp调用LockBits后未执行UnlockBits,会引发图像资源锁定问题。
修复方法
  • 删除遍历单个边缘点的内层循环,每个Blob的边缘点是一组闭合轮廓,不需要逐个点传入绘制方法。
  • 调用已实现的ToPointsArray方法,将AForge的IntPoint列表转换为System.Drawing.Point数组,再传入DrawPolygon完成绘制。
  • 补全原图的UnlockBits调用,避免资源锁定问题。

修改后的核心代码片段如下:

// 拷贝完图像数组后立刻解锁原图bmp
Marshal.Copy(ptr, data, 0, data.Length);
bmp.UnlockBits(BmpData); // 补全缺失的解锁调用

// --- 省略中间图像处理逻辑 ---

for (int i = 0; i < blobs.Length; i++)
{
    edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
    // 转换点类型后直接传入绘制,删除内层遍历单个点的循环
    System.Drawing.Point[] drawPoints = ToPointsArray(edgePoints);
    g.DrawPolygon(redPen, drawPoints);
}

可选优化:将Pen、Graphics、Bitmap等实现了IDisposable接口的对象放入using块中,可自动完成资源释放,避免手动调用Dispose遗漏导致的内存问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:15:39