Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCVSharp AccessViolationException in FindCirclesGrid

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());
like image 416
Ronan Thibaudau Avatar asked Jul 03 '26 00:07

Ronan Thibaudau


1 Answers

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());
    }
}
like image 192
Peter Wishart Avatar answered Jul 05 '26 16:07

Peter Wishart