使用Emgu CV v4.9实现区域截图与模板匹配时遇参数无效错误
问题分析与修复
问题根源
你把截图生成的bitmap放在了using语句块中,using会在块执行完毕后自动释放bitmap的资源。当后续执行Emgu.CV.BitmapExtension.ToImage<Bgr, Byte>(bitmap)时,bitmap已经是被释放的无效对象,这就触发了System.ArgumentException: Parameter is not valid异常。
修复方案
把所有需要使用bitmap的代码逻辑移到using (bitmap)的块内部,确保在bitmap资源释放前完成所有相关操作。同时给Emgu.CV的图像对象也加上using,避免资源泄漏。
修复后的完整代码
using System.Runtime.InteropServices; using System.Windows; using System.Windows.Forms; using Emgu.CV; using Emgu.CV.Structure; using Emgu.CV.CvEnum; using Emgu.CV.Util; private void btnStart_Click(object sender, EventArgs e) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 1200; rect.bottom = 800; Rectangle bounds = new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); // 将bitmap的using范围覆盖所有依赖它的操作 using (var bitmap = new Bitmap(bounds.Width, bounds.Height)) { using (var g = Graphics.FromImage(bitmap)) { g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size); } // 此时bitmap未被释放,可正常转换 Image<Bgr, Byte> source = Emgu.CV.BitmapExtension.ToImage<Bgr, Byte>(bitmap); // 也可以用扩展方法写法 // Image<Bgr, Byte> source = bitmap.ToImage<Bgr, Byte>(); using (Image<Bgr, byte> template = new Image<Bgr, byte>("scr-over/temple.bmp")) using (Image<Bgr, byte> imageToShow = source.Copy()) { using (Image<Gray, float> result = source.MatchTemplate(template, Emgu.CV.CvEnum.TemplateMatchingType.CcoeffNormed)) { double[] minValues, maxValues; Point[] minLocations, maxLocations; result.MinMax(out minValues, out maxValues, out minLocations, out maxLocations); if (maxValues[0] > 0.9) { Rectangle match = new Rectangle(maxLocations[0], template.Size); imageToShow.Draw(match, new Bgr(Color.Red), 1); pictureBox1.Image = imageToShow.ToBitmap(); } } imageToShow.Save("scr-over/result.bmp"); } } }
额外说明
- 给
template、imageToShow这类Emgu.CV图像对象添加using,能确保它们的非托管资源被及时释放,避免内存堆积。 - 所有依赖
bitmap的操作必须放在其using块内部,否则会再次出现资源无效的异常。
内容的提问来源于stack exchange,提问作者Mari Rveze
相关产品推荐
相关产品推荐

