OpenCVSharp AccessViolationException in FindCirclesGrid

I'm using OpenCVSharp to run some calibration tests, but I can't get FindCirclesGrid to work, I get an unexpected AccessViolationException when I call FindCirclesGrid.

I'm not sure if I could be wrong as the first two lines are exactly the same as in the samples, the centers are not initialized as it is an output parameter, and everything passed to OpenCV seems to be initialized in the OpenCVSharp 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 am using the latest OpenCVSharp straight from nuget

Edit1: I forgot to mention this in the question, but I already tried adding foillowing after FindCirclesGrid to ensure that the objects weren't collected incorrectly before they did, it didn't change anything. Also the error is debugged and debugged.

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

      

+3


source to share


4 answers


I've reported a bug to github. It looks like it's fixed, but I can't check it atm.



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

0


source


This was a bug in OpenCvSharp , I posted a fix that was included in the NuGet 2.4.10.20150604 release.

There are two calls to interop, exported by OpenCvSharpExtern

the C ++ wrapper dll that OpenCvSharp uses internally: calib3d_findCirclesGrid_InputArray

and calib3d_findCirclesGrid_vector

.

Their signatures differ only in the use of C ++ types cv::_OutputArray

and std::vector<cv::Point2f>

for the parameter centers

, but in the extern C # definitions they are both defined as IntPtr

, making the methods interchangeable at compile time in C #.



The git affect (latest commit e14c711958) has both C # overloads FindCirclesGrid

mapped to the same interop call calib3d_findCirclesGrid_InputArray

, so the using overload Point2f[]

does not work, since C ++ code does not work, t get the expected parameter.

eg. using a calibration image here as 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());
    }
}

      

+1


source


Garbage collection can be performed as long as the circle mesh is found. If you run the application in free mode without debugging, the JIT compiler will perform optimization and the object may be garbage collected before the operation completes on the unmanaged resource. This will most likely cause the application to crash.

The problem can be easily fixed: you just need to keep the link to the current image, the size of the picture, etc. until the method exits, or try using 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);
}

      

0


source


Instead of writing this line

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

      

Try the following:

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

As, the FindCirclesGrid () function takes a fourth argument as a constant, depending on your circle pattern.

It can be one of the following:

CALIB_CB_SYMMETRIC_GRID uses a symmetrical circle structure. CALIB_CB_ASYMMETRIC_GRID uses an asymmetric circle pattern. CALIB_CB_CLUSTERING uses a special mesh detection algorithm. It is more resistant to perspective distortion, but much more sensitive to background noise.

You can use the fifth argument of type Ptr (FeatureDetector) to find blobs, such as dark circles on a light background.

Or ELSE you can try to convert "FindCirclesGridFlag.AsymmetricGrid" - integer. eg (int)FindCirclesGridFlag.AsymmetricGrid

Hope I understood your question.

0


source







All Articles