VideoCapture.Retrieve() 上的 System.AccessViolationException - EmguCV / OpenCV

Posted

技术标签:

【中文标题】VideoCapture.Retrieve() 上的 System.AccessViolationException - EmguCV / OpenCV【英文标题】:System.AccessViolationException on VideoCapture.Retrieve() - EmguCV / OpenCV 【发布时间】:2018-06-21 18:40:51 【问题描述】:

我是打开 cv 的新手,我正在尝试使用人脸识别功能,但有一次遇到了麻烦。对 VideoCapture-Object 调用 Retrieve()-Method 会在以下三种情况之一中引发 System.AccessViolationException。我发现了很多关于这个问题的主题,但没有解决方案。

这是我得到的 StackTrace:

bei Emgu.CV.CvInvoke.cveVideoCaptureRetrieve(IntPtr capture, IntPtr 图像,Int32 标志)

bei Emgu.CV.VideoCapture.Retrieve(IOutputArray image, Int32 channel)

bei OpenCVGenericAssembly.OpenCVGenericAssembly.Capture(String sensorSerialNo,FeatureType 特征,布尔压缩,Int32 超时)在 C:\Users\sl\Documents\Source\Share\OpenCVGenericAssembly\OpenCVGenericAssembly\OpenCVGenericAssembly.cs:Zeile 81.

bei OpenCVGenericAssembly.OpenCVGenericAssembly.Enroll(String sensorSerialNo, String firstName, String lastName, String company, FeatureType 特征,Int32 模板目的地,布尔压缩, Int32 timeOut, String connectionString, String templateQuery) in C:\Users\sl\Documents\Source\Share\OpenCVGenericAssembly\OpenCVGenericAssembly\OpenCVGenericAssembly.cs:Zeile 125.

bei Testing.Program.Main(String[] args) in C:\Users\sl\Documents\Source\Share\OpenCVGenericAssembly\Testing\Program.cs:Zeile 20.

我正在调用一个 Enroll Method,它除了调用 Capture-Method 并等待它的响应之外什么都不做。 Capture-Method 将一直运行,直到它准确地检测到一张脸,然后将其返回。这就是 Capture-Method 的样子:

public DResponse Capture(string sensorSerialNo, FeatureType feature, bool compressed = false, int timeOut = 0)

    capture = new VideoCapture(); 
    DResponse rsp = DResponse();

    while(string.IsNullOrWhiteSpace(rsp.templateData))
    
        using (Mat mat = new Mat())
        
            capture.Retrieve(mat);
            Image<Bgr, Byte> currentFrame = mat.ToImage<Bgr, Byte>();

            if (currentFrame != null)
            
                Image<Gray, Byte> grayFrame = currentFrame.Convert<Gray, Byte>();

                Rectangle[] detectedFaces = cascadeClassifier.DetectMultiScale(grayFrame, DMS_SCALE_FACTORS, DMS_MIN_NEIGHBORS);

                if (detectedFaces.Length == 1)
                
                    Image<Gray, byte> result = currentFrame.Copy(detectedFaces[0]).Convert<Gray, byte>().Resize(IMG_WIDTH, IMG_HEIGHT, Emgu.CV.CvEnum.Inter.Cubic);
                    result._EqualizeHist();
                    rsp.templateData = Convert.ToBase64String(result.Bytes);
                    break;
                
                Thread.Sleep(100);
            
        
    

    return rsp;

我首先尝试了有关此的教程。这是一个 wpf 应用程序,显示视频流和检测到的面部周围的框架(加上一个名字,如果一个人被识别)。它非常相似,但是他们在教程中使用了 DispatcherTimer,我不能使用它,因为我的代码应该用作程序集。无论如何,这段代码不会抛出这个错误,所以也许这会帮助有人在我上面的源代码中捕获问题。

private void Window_Loaded(object sender, RoutedEventArgs e)

    capture = new VideoCapture();
    haarCascade = new CascadeClassifier(System.AppDomain.CurrentDomain.BaseDirectory + "haarcascade_frontalface_alt_tree.xml");
    timer = new DispatcherTimer();
    timer.Tick += new EventHandler(timer_Tick);
    timer.Interval = new TimeSpan(0, 0, 0, 0, 1);
    timer.Start();


void timer_Tick(object sender, EventArgs e)

    Mat mat = new Mat();
    capture.Retrieve(mat);
    Image<Bgr, Byte> currentFrame = mat.ToImage<Bgr, Byte>();

    if (currentFrame != null)
    
        Image<Gray, Byte> grayFrame = currentFrame.Convert<Gray, Byte>();
        Rectangle[] detectedFaces = haarCascade.DetectMultiScale(grayFrame, 1.1, 1);

        for (int i = 0; i < detectedFaces.Length; i++)
        
            result = currentFrame.Copy(detectedFaces[i]).Convert<Gray, byte>().Resize(100, 100, Emgu.CV.CvEnum.Inter.Cubic);
            result._EqualizeHist();

            currentFrame.Draw(detectedFaces[i], new Bgr(System.Drawing.Color.Green), 3);

            if (eigenRecog.IsTrained)
            
                // do some stuff
            
        

        image1.Source = ToBitmapSource(currentFrame);
    

有什么提示吗?任何问题?我感谢每一个输入! stl

【问题讨论】:

好吧,有时这很容易......在教程代码中,在整个运行时使用相同的 VideoCapture 对象,这就是为什么那里不会发生错误的原因。因为我每次调用上面的 Capture() 方法时都会初始化一个新的 VideoCapture,所以我需要在最后处理它。就是这样…… 你可以把这个写成答案 【参考方案1】:

必须处置 VideoCapture-Object(手动或将其放入 using 块中)。这样就解决了问题。

【讨论】:

以上是关于VideoCapture.Retrieve() 上的 System.AccessViolationException - EmguCV / OpenCV的主要内容,如果未能解决你的问题,请参考以下文章

上划线怎么打啊????

电脑上GetTickCount64在哪里

.htaccess:在所有页面上强制 www,在一个页面上强制 https,在所有其他页面上强制 http

为啥当我在 grails 上删除一对多关系上的父级时,会在子级上调用 beforeInsert 事件?

地理定位在笔记本电脑上工作,但不在智能手机上

键盘上的PERIOD键在啥地方?