c# emgu/opencv 使用抛出异常 - 试图读取或写入受保护的内存

Posted

技术标签:

【中文标题】c# emgu/opencv 使用抛出异常 - 试图读取或写入受保护的内存【英文标题】:c# emgu/opencv usage throwing exception - Attempted to read or write protected memory 【发布时间】:2021-09-03 14:11:47 【问题描述】:

我已经在这里访问了很多关于 System.AccessViolationException: 'Attempted to read or write protected memory. 错误的答案,它们似乎都是关于与图片无关的其他事情。

我正在学习图像处理,但我仍然在学习软件调试。我正在尝试使用基于 BRISK 的基于特征的图像检测和蛮力方法在另一个图像中搜索图像。但是由于某种原因,每次我运行并单击 button2 时都会出现上述错误,我不知道如何调试它。 matcher.KnnMatch(sceneDescriptor, matches, k); 行抛出异常,当我将鼠标悬停在它上面时,matches 的值为 null。

我在 Visual Studio 2019 中使用 NuGet 安装 Emgu.CV vs 4.5.1、Emgu.cv.bitmap、emgu.cv.runtime.windows 4.5.1。我什至尝试将我的编译模式从 x86 更改为 x64。我不知道我做错了什么。

文件 - myImgprocessing.cs:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Emgu;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using Emgu.CV.Util;
using Emgu.CV.Features2D; // for brisk/ feature detectors

namespace mine

    class MyImageProcessing
    

    // store in memory any images we want to use
    Dictionary<string, Image<Bgr, byte>> imgDict; // imgDict.Add("shark",img);

    public Bitmap findImgFB(Image<Bgr, byte> sourceImg, Image<Bgr, byte> targetImg)
    

        if ((sourceImg != null) && (targetImg != null))
        

            var localImgSourceC = sourceImg.Clone();
            var localImgSource = localImgSourceC.ToBitmap().ToImage<Gray, byte>();

            var localImgTargetC = targetImg.Clone();
            var localImgTarget = localImgTargetC.ToBitmap().ToImage<Gray, byte>();
            //return localImgTarget.AsBitmap();

            var myfoundPoints = processFBBrutforce(localImgTarget, localImgSource);

            if(myfoundPoints != null)
            
                // draw it now
                CvInvoke.Polylines(sourceImg, myfoundPoints, true, new MCvScalar(0,0,255),5);
            
            else
            
                MessageBox.Show("cant find points to draw");
            

            return sourceImg.AsBitmap(); // efficient way to convert gray image byte to grayscale

        
        
        return new Bitmap(5, 5);
    

    private static VectorOfPoint processFBBrutforce(Image<Gray, byte> target, Image<Gray, byte> sceneimg)
    
        try
        
            //
            // initialization start
            VectorOfPoint pointsToReturn = null;
            Mat homography = null;
            VectorOfKeyPoint targetKeyPoints = new VectorOfKeyPoint(); // key points stored here
            VectorOfKeyPoint sceneKeyPoints = new VectorOfKeyPoint();
            VectorOfVectorOfDMatch matches = null; // storing matches
            Mat sceneDescriptor = new Mat();
            Mat targetDescriptor = new Mat();

            int k = 2; // NUMBER OF NEAREST MATCHES TO RETURN for uniquenes
            Double uniqueThreshold = 0.80; // this is for finding neighbour matches so that it does not find duplicates and only uniques, tweak this number for results
            Mat mask;

            //descriptor and feature detection to use, tweak this for different results
            Brisk featureDetector = new Brisk();
            featureDetector.DetectAndCompute(target, null, targetKeyPoints, targetDescriptor,false); // give it img, place to store key points/descriptor, and false cus we need it to get key points
            featureDetector.DetectAndCompute(sceneimg, null, sceneKeyPoints, sceneDescriptor, false);
            // initialization end
            //

            // matching part - this is a brute-force matcher 
            BFMatcher matcher = new BFMatcher(DistanceType.Hamming);// we have to use 'hamming' distance calculator method because we are using BRISK feature detector above, can tweak respectively
            matcher.Add(targetDescriptor);// give it model 
            matcher.KnnMatch(sceneDescriptor, matches, k);// match it with model and store in matches variable

            // create a mask and set those values to 255
            mask = new Mat(matches.Size,1,Emgu.CV.CvEnum.DepthType.Cv8U, 1);// 1 column, 8bit unsigned depth type, 1 channel image
            mask.SetTo(new MCvScalar(255));

            // goes through the masks and looks for match and sets to 255 or 0 for no match
            Features2DToolbox.VoteForUniqueness(matches, uniqueThreshold, mask);

            // give only the allowed scaled and rotated matches so it doesnt go past a certain point, this rejects any matches without the below requirements
            int count = Features2DToolbox.VoteForSizeAndOrientation(targetKeyPoints, sceneKeyPoints, matches, mask, 1.5, 20); // scale = 1.5 , bins/rotation cap = 20

            //
            // now we can finally get the homography for the object 
            //

            // if we dont have 4 matches, we cant build homography match
            if(count >= 4)
            
                homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(targetKeyPoints, sceneKeyPoints, matches, mask, 
                    5); // adding mask will help to bring the best and unique matches - tweak the last peramiter
            

            if (homography != null)
            
                Rectangle rect = new Rectangle(Point.Empty, target.Size); // draw rectangle same size as the target image

                // use homography to tell it where to draw it as it uses relationship between image and keypoints

                // make array of the points as that what the transform method takes
                PointF[] pts = new PointF[]
                
                    new PointF(rect.Left, rect.Bottom),
                    new PointF(rect.Right, rect.Bottom),
                    new PointF(rect.Right, rect.Top),
                    new PointF(rect.Left, rect.Top)
                ;

                pts = CvInvoke.PerspectiveTransform(pts, homography); // put it into the pts

                Point[] points = Array.ConvertAll<PointF, Point>(pts, Point.Round); // transform into vectorofpoints array to return

                pointsToReturn = new VectorOfPoint(points);

            

            return pointsToReturn;

        
        catch (Exception e)
        
            throw new Exception(e.Message);
        



        

然后在我的主窗口窗体中,我将目标和场景图像传递给它,并调用该方法以返回要显示的位图。但它每次都会在该特定行上出错:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Diagnostics;
using Emgu.CV;
using Emgu.CV.Structure;

namespace mine


    public partial class mainform: Form
    

        private Bitmap currentPassedImgBmp;

        private void button2_Click_1(object sender, EventArgs e)
        

            MyImageProcessing newImgProc = new MyImageProcessing();

            Image<Bgr, byte> testTargetImg = new Image<Bgr, byte>(@"C:\items\target.png");
            Image<Bgr, byte> sourceImgFromBMP = new Image<Bgr, byte>(@"C:\items\searchref.png");
            // Image<Bgr, byte> sourceImgFromBMP = currentPassedImgBmp.ToImage<Bgr, byte>();

            var mybitmap = newImgProc.findImgFB(sourceImgFromBMP, testTargetImg);


     
  
    

任何指导或指出正确的方向都会有所帮助,我花了将近一整天的时间浏览不同的答案和教程,这些答案和教程要么已经过时,要么指的是改变了上下文的视频。强>

【问题讨论】:

你说每次我尝试编译我都会收到上述错误 - 但听起来你在时看到了问题运行你的程序,因为你看到一个异常被抛出?编译时和运行时错误需要不同的处理。 抱歉,现在编辑我的答案 【参考方案1】:

我没有测试我提出的解决方案,但我确信您需要在将匹配项传递给 KnnMatch 方法之前对其进行初始化:

VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();

我还要指出,您需要注意正确处理持有非托管资源的对象(例如 EmguCV 的 Mat 对象),否则一旦超出实验步骤,您将很快遇到内存问题。

【讨论】:

太棒了!只需更改 VectorOfVectorOfDMatch 匹配 = null;到您显示的代码已使其工作。

以上是关于c# emgu/opencv 使用抛出异常 - 试图读取或写入受保护的内存的主要内容,如果未能解决你的问题,请参考以下文章

使用 Emgu OpenCV 计算直方图

访问冲突异常之谜

如何使用 twain/emgu/open cv 获得良好的清晰度?

C# PrintQueue AddJob printingHandle 抛出空异常

c# throw抛出上一个异常

dll Matlab实例在c#中运行release时抛出异常