Emgu CV 人脸识别:在多个文件上并行运行 DetectHaarCascade 问题

Posted

技术标签:

【中文标题】Emgu CV 人脸识别:在多个文件上并行运行 DetectHaarCascade 问题【英文标题】:Emgu CV Face Recognition: Running DetectHaarCascade on multiple files in parallel issues 【发布时间】:2012-03-22 13:22:09 【问题描述】:

我正在尝试通过在多个文件上同时运行 DetectHaarCascade 人脸检测来提高检测图像中人脸的速度。但是我遇到了 AccessViolationException,想知道是否有人有关于如何并行运行 EMGU CV 人脸检测的示例。

这是我编写的一个简单测试,其中有 98 个图像要检测:

    [TestMethod]
    public void TestDetectParallel()
    
        var face = new HaarCascade("haarcascade_frontalface_default.xml");
        var images =
            Directory.EnumerateFiles(Environment.CurrentDirectory, "*.jpg").AsParallel().Select(
                file => new Image<Gray, byte>(file));
        Parallel.ForEach(
            images, 
            image =>
            
                image.DetectHaarCascade(face, 1.2, 10, HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
                                        new Size(20, 20));
            );
    

因为我是并行运行它,所以我遇到了一些多线程问题,带有堆栈跟踪:

System.AccessViolationException was unhandled by user code
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=Emgu.CV
  StackTrace:
       at Emgu.CV.CvInvoke.cvHaarDetectObjects(IntPtr image, IntPtr cascade, IntPtr storage, Double scaleFactor, Int32 minNeighbors, HAAR_DETECTION_TYPE flags, Size minSize)
       at Emgu.CV.Image`2.<>c__DisplayClassa.<DetectHaarCascade>b__6(IImage img, Int32 channel) in C:\Emgu\emgucv-windows-x86 2.3.0.1416\Emgu.CV\Image.cs:line 888
       at Emgu.CV.Image`2.ForEachDuplicateChannel[TReturn](Func`3 conv) in C:\Emgu\emgucv-windows-x86 2.3.0.1416\Emgu.CV\Image.cs:line 1229
       at Emgu.CV.Image`2.DetectHaarCascade(HaarCascade haarObj, Double scaleFactor, Int32 minNeighbors, HAAR_DETECTION_TYPE flag, Size minSize) in C:\Emgu\emgucv-windows-x86 2.3.0.1416\Emgu.CV\Image.cs:line 904
       at PhotosortService.UnitTest.UnitTest1.<>c__DisplayClass3.<TestDetectParallel>b__1(Image`2 image) in C:\Users\bchiu\Desktop\PhotosortService\PhotosortService.UnitTest\UnitTest1.cs:line 35
       at System.Threading.Tasks.Parallel.<>c__DisplayClass32`2.<PartitionerForEachWorker>b__30()
       at System.Threading.Tasks.Task.InnerInvoke()
       at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
       at System.Threading.Tasks.Task.<>c__DisplayClass7.<ExecuteSelfReplicating>b__6(Object )
       at System.Threading.Tasks.Task.ExecuteSelfReplicating(Task root)
       at System.Threading.Tasks.Task.Execute()
       at System.Threading.Tasks.Task.ExecutionContextCallback(Object obj)
       at System.Threading.ExecutionContext.runTryCode(Object userData)
       at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
       at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
       at System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(Task task, Boolean taskWasPreviouslyQueued)
       at System.Threading.Tasks.TaskScheduler.TryRunInline(Task task, Boolean taskWasPreviouslyQueued, Object threadStatics)
       at System.Threading.Tasks.Task.InternalRunSynchronously(TaskScheduler scheduler)
       at System.Threading.Tasks.Task.RunSynchronously(TaskScheduler scheduler)
       at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
       at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
       at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
       at PhotosortService.UnitTest.UnitTest1.TestDetectParallel() in C:\Users\bchiu\Desktop\PhotosortService\PhotosortService.UnitTest\UnitTest1.cs:line 33
  InnerException: 

非常感谢!

【问题讨论】:

【参考方案1】:

通过给每个线程一个var face = new HaarCascade("haarcascade_frontalface_default.xml");对象来解决。

[TestMethod]
public void TestDetectParallel()
        
    var images =
        Directory.EnumerateFiles(Environment.CurrentDirectory, "*.jpg").AsParallel().Select(
            file => new Image<Gray, byte>(file));
    Parallel.ForEach(
        images, 
        image =>
        
            var face = new HaarCascade("haarcascade_frontalface_default.xml");
            image.DetectHaarCascade(face, 1.2, 10, HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
                                    new Size(20, 20));
        );

【讨论】:

以上是关于Emgu CV 人脸识别:在多个文件上并行运行 DetectHaarCascade 问题的主要内容,如果未能解决你的问题,请参考以下文章

C# - Emgu CV - 人脸识别代码在 EigenObjectRecognizer 处停止执行并无错误退出

C# - Emgu Cv - 人脸识别 - 将保存到 Access 数据库的人脸训练集作为二进制文件加载到 EigenObjectRecognizer 中以进行人脸识别

利用Emgu.CV实现人脸识别详解 (C#)--附源码

EMGU CV 2.4.9 人脸识别准确率问题

如何将 Emgu.cv 用于未知人员?

Emgu CV EigenObjectRecognizer 不工作