找到你要的答案

Q:OpenCVSharp AccessViolationException in FindCirclesGrid

Q:在FindCirclesGrid opencvsharp accessviolationexception

I'm using OpenCVSharp to run some calibration tests but i can't seem to get FindCirclesGrid to work, i'm getting a really unexpected AccessViolationException when calling FindCirclesGrid.

I'm not sure what i could be doing wrong as the first two line are pretty much exactly as in samples,centers is not initialized as it is an output parameter and everything that is passed down to OpenCV seems to be initialized in OpenCVSharp's wrapper function.

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

I'm using the latest OpenCVSharp straight from nuget

Edit1 : i forgot to mention this in the question but i have already tried adding the foillowing after FindCirclesGrid to ensure objects weren't wrongly collected before they should, this changed nothing. Also the bug happens just the same in debug and release.

 Console.Writeline(im.ToString());
 Console.Writeline(patternsize.ToString());
 Console.Writeline(centers.ToString());
 Console.Writeline(f.ToString());

我用opencvsharp运行一些校准测试,但我似乎不能让FindCirclesGrid去工作,我得到一个很意外的accessviolationexception当叫FindCirclesGrid。

我不知道我可以做错误的作为第一个线是相当准确的样品中,中心没有初始化是一个输出参数以及一切传递到OpenCV似乎opencvsharp的包装函数初始化。

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

我使用的是最新opencvsharp直接从NuGet

置:我忘了提这个问题但我已经试着在FindCirclesGrid确保对象没有错误地收集之前就应该加入foillowing,什么都没有改变。此外,错误发生在调试和释放相同。

 Console.Writeline(im.ToString());
 Console.Writeline(patternsize.ToString());
 Console.Writeline(centers.ToString());
 Console.Writeline(f.ToString());
answer1: 回答1:

I reported a bug at github. It seems to be fixed by now, but I can't test it atm.

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

我曾在GitHub的bug。现在看来好像是固定的,但我不能测试它。

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

answer2: 回答2:

This was a bug in OpenCvSharp, I submitted a fix which was included in NuGet release 2.4.10.20150604.

There are two interop calls exported by the C++ wrapper dll OpenCvSharpExtern that OpenCvSharp uses internally: calib3d_findCirclesGrid_InputArray and calib3d_findCirclesGrid_vector.

Their signatures differ only by the use of C++ types cv::_OutputArray and std::vector<cv::Point2f> for the centers parameter, but in the C# extern definitions these are both defined as IntPtr, making the methods interchangable at compile time in C#.

The affect git version (latest commit e14c711958) has both C# overloads of FindCirclesGrid mapped to the same interop call calib3d_findCirclesGrid_InputArray, hence the overload using Point2f[] doesn't work, as the C++ code doesn't get the parameter it expects.

E.g. using a simulation of the calibration image here as the input image:

// 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());
    }
}

这是OpenCvSharp的一个bug,我提交了一份修正进行2.4.10.20150604 NuGet发布。

有两个互操作调用的C++封装的DLL opencvsharpextern,opencvsharp内部用的出口:calib3d_findcirclesgrid_inputarray和calib3d_findcirclesgrid_vector。

他们的签名不同,只有通过C++类型品种使用::_outputarray和std::vector <;简历::point2f >;为中心的参数,但在C # extern定义这些都定义为IntPtr,制作方法可在编译C #时间。

影响Git版本(最新提交e14c711958)具有C #重载findcirclesgrid映射到同一calib3d_findcirclesgrid_inputarray互操作调用,因此超载使用point2f [ ]不工作,为C++代码没有预计参数。

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

// 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());
    }
}
answer3: 回答3:

The garbage collection maybe executed while the circle grid is being found. If you run your application in release mode without debugging, then JIT compiler will perform optimizations and the object can be subject to garbage collection before the operation over the unmanaged resource is finished. Most likely it will result in the application crash.

The issue can be easily fixed: it’s just necessary to keep reference to the current image, pattern size, etc. till the method completes its work, or try to use GC.KeepAlive method:

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

在发现圆网格时可能执行垃圾回收。如果你没有调试运行在发布模式下您的应用程序,然后执行优化,JIT编译器将对象可受垃圾收集操作前在非托管资源完成。最有可能会导致应用程序崩溃。

这个问题可以很容易地固定:只是要保持参考当前图像,图形尺寸等方法,直到完成它的工作,或尝试使用gc.keepalive方法:

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);
}
answer4: 回答4:

Instead of writing this line

var f = Cv2.FindCirclesGrid(im, patternsize, out centers, FindCirclesGridFlag.AsymmetricGrid);

Try This:

var f = Cv2.FindCirclesGrid(im, patternsize, out centers, CALIB_CB_ASYMMETRIC_GRID);

As, FindCirclesGrid() function takes fourth argument as a constant depending upon your pattern of circles.

It can be one of the following:

CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles. CALIB_CB_ASYMMETRIC_GRID uses asymmetric pattern of circles. CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to perspective distortions but much more sensitive to background clutter.

You can use Fifth argument of type Ptr(FeatureDetector) for finding blobs like dark circles on light background.

Or ELSE you can try converting "FindCirclesGridFlag.AsymmetricGrid" to integer. e.g. (int)FindCirclesGridFlag.AsymmetricGrid Hope I have understood your question.

而不是写这行

var f = Cv2.FindCirclesGrid(im, patternsize, out centers, FindCirclesGridFlag.AsymmetricGrid);

试试这个:

var =简历FindCirclesGrid(IM,patternsize,出中心,calib_cb_asymmetric_grid);

因为,findcirclesgrid()函数需要第四个参数为常数,取决于你的圈模式。

它可以是下列之一:

CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles. CALIB_CB_ASYMMETRIC_GRID uses asymmetric pattern of circles. CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to perspective distortions but much more sensitive to background clutter.

你可以使用类型第五个参数(PTR featuredetector)寻找斑点像光背景的黑眼圈。

Or ELSE you can try converting "FindCirclesGridFlag.AsymmetricGrid" to integer. e.g. (int)FindCirclesGridFlag.AsymmetricGrid Hope I have understood your question.

c#  opencv  access-violation  opencvsharp