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());
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());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With