c# emgu/opencv usage throwing exception - 试图读取或写入受保护的内存

c# emgu/opencv usage throwing exception - Attempted to read or write protected memory

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

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

        }

然后在我的主 windows 表单中,我将目标和场景图像传递给它,并调用该方法以获取要显示的位图。但它每次都在该特定行上出错:

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);


     }
  }
    }

任何指导或指向正确的方向都会有所帮助,我花了将近一整天的时间来研究不同的答案和教程,这些答案和教程要么已经过时,要么参考了改变上下文的视频好像。

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

VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();

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