首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenCVSharp AccessViolationException in FindCirclesGrid

OpenCVSharp AccessViolationException in FindCirclesGrid
EN

Stack Overflow用户
提问于 2015-05-02 16:12:34
回答 4查看 1.9K关注 0票数 3

我正在使用OpenCVSharp运行一些校准测试,但我似乎无法让FindCirclesGrid工作,我在调用FindCirclesGrid时得到了一个非常意外的AccessViolationException。

我不知道我可能做错了什么,因为前两行与样例中几乎完全一样,中心没有初始化,因为它是输出参数,传递给OpenCV的所有内容似乎都是在OpenCVSharp的包装函数中初始化的。

代码语言:javascript
复制
void test()
{
    Mat im = Cv2.ImRead(@"path_to_my_file.jpg");
    Size patternsize = new Size(11, 4);
    Point2f[] centers;
    var f = Cv2.FindCirclesGrid(im, patternsize, out centers, FindCirclesGridFlag.AsymmetricGrid);
}

我用的是来自nuget的最新OpenCVSharp

Edit1 :我忘了在问题中提到这一点,但我已经尝试过在FindCirclesGrid之后添加浮雕,以确保对象在未被错误收集之前不会被错误地收集,这并没有改变什么。同样,在调试和发布过程中,错误也会发生。

代码语言:javascript
复制
 Console.Writeline(im.ToString());
 Console.Writeline(patternsize.ToString());
 Console.Writeline(centers.ToString());
 Console.Writeline(f.ToString());
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-06-04 13:55:27

我在github报告了一个窃听器。它现在似乎已经修好了,但我不能测试它的自动取款机。

https://github.com/shimat/opencvsharp/issues/106

票数 0
EN

Stack Overflow用户

发布于 2015-05-05 16:43:31

这个是OpenCvSharp中的一个bug,我提交了一个修复程序,它包含在NuGet版本2.4.10.20150604中。

C++包装器dll OpenCvSharpExtern导出了OpenCvSharp内部使用的两个互操作调用:calib3d_findCirclesGrid_InputArraycalib3d_findCirclesGrid_vector

它们的签名仅通过对C++类型cv::_OutputArraystd::vector<cv::Point2f>参数的使用而不同,但在C#外部定义中,它们都被定义为IntPtr,使得在C#编译时方法可以互换。

it版本(最新的提交e14c711958)将两个C#重载的FindCirclesGrid映射到相同的互操作调用calib3d_findCirclesGrid_InputArray,因此使用Point2f[]的重载无法工作,因为C++代码没有得到它期望的参数。

例如,使用校准图像的模拟这里作为输入图像:

代码语言:javascript
复制
// Fails with NuGet package OpenCvSharp-AnyCPU 2.4.10.20150320. 
using (var imageStream = new MemoryStream())
{
    using (var circleBoard = new System.Drawing.Bitmap(650, 850))
    using (var g = System.Drawing.Graphics.FromImage(circleBoard))
    {
        g.Clear(System.Drawing.Color.White);
        for (int y = 0; y <= 10; y += 1)
            for (int x = 0; x <= 3; x += 1)
            {
                var dx = 10 + x * 150;
                var dy = 10 + y * 75;
                g.FillEllipse(System.Drawing.Brushes.Black, dx + ((y + 1) % 2) * 75, dy, 50, 50);
            }
        circleBoard.Save(imageStream, System.Drawing.Imaging.ImageFormat.Png);
    }

    Mat im = Cv2.ImDecode(imageStream.GetBuffer(), OpenCvSharp.LoadMode.GrayScale);
    Size patternsize = new Size(4, 11);

    var centers = new List<Point2f>();
    if (Cv2.FindCirclesGrid(im, patternsize, OutputArray<Point2f>.Create(centers), FindCirclesGridFlag.AsymmetricGrid | FindCirclesGridFlag.Clustering))
    {
        // Ok, finds 44 circles
        Console.WriteLine(centers.Count());
    }
    Point2f[] centers2 = null;
    if (Cv2.FindCirclesGrid(im, patternsize, out centers2, FindCirclesGridFlag.AsymmetricGrid | FindCirclesGridFlag.Clustering))
    {
        // Crashes with AccessViolationException
        Console.WriteLine(centers2.Count());
    }
}
票数 1
EN

Stack Overflow用户

发布于 2015-05-05 11:16:17

在查找圆网格时,可能会执行垃圾收集。如果您在不进行调试的情况下以发布模式运行应用程序,那么JIT编译器将执行优化,并且在非托管资源上的操作完成之前,对象可以被垃圾收集。很可能会导致应用程序崩溃。

这个问题可以很容易地解决:只需保持对当前图像、模式大小等的引用,直到该方法完成其工作,或者尝试使用GC.KeepAlive方法:

代码语言:javascript
复制
void test()
{
    Mat im = Cv2.ImRead(@"path_to_my_file.jpg");
    Size patternsize = new Size(11, 4);
    Point2f[] centers;
    var f = Cv2.FindCirclesGrid(im, patternsize, out centers, FindCirclesGridFlag.AsymmetricGrid);
    GC.KeepAlive(this);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30004528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档