i am using the new EmguCV 3.0.0 alpha to detect a chessboard with webcam and have an understanding problem with the corners matrix.
Size patternSize = new Size(5, 4);
Matrix<float> corners = new Matrix<float>(1, 2);
bool find = CvInvoke.FindChessboardCorners(grayFrame, patternSize, corners, CalibCbType.AdaptiveThresh | CalibCbType.FilterQuads);
CvInvoke.DrawChessboardCorners(grayFrame, patternSize, corners, find);
if (find)
{
Console.Write(corners.Size);
}
The chessboard will be detected and shown correct!
But, how big must be the size of the corners matrix and how do i extract the corner positions?
All samples i found on internet are using older versions of EmguCV and there is a complete different syntax now. I would use the older version but the newer alpha is much faster and timing is a big issue in my app.
The CvInvoke.FindChessboardCorners
Method has this signature1:
public static bool FindChessboardCorners(
IInputArray image,
Size patternSize,
IOutputArray corners,
CalibCbType flags = CalibCbType.Default|CalibCbType.AdaptiveThresh|CalibCbType.NormalizeImage
)
The third parameter is of type IOutputArray
2. I do not understand why they introduced these super generic input/output interfaces that are implemented by various classes that cannot be used interchangeably.
You are right, the Matrix
class does implement that interface (via super class CvArray
) and thus your code compiles.
However, CvInvoke.FindChessboardCorners
is supposed to return a few points (depending on the size of the pattern). I googled for classes that implement IOutputArray
and found VectorOfPoints
. That kind of made sense to me, more so than using a Matrix
.
I hacked together a little console app for calibration that reads all image files from a directory and detects the corners in them, because for me it makes more sense to capture the images beforehand.
That should give you a starting point:
public class Calibration
{
static void Main(string[] args)
{
// chessboard pattern size
Size patternSize = new Size(9, 7);
// for each image, have one Image object and one VectorOfPoints
// for many images have a List of each
List<VectorOfPoint> corners = new List<VectorOfPoint>();
List<Image<Gray, Byte>> images = new List<Image<Gray, byte>>();
// get paths to image files
string[] imageFiles = Directory.GetFiles(@"C:\your\directory", "*.jpg");
// for every image
foreach (string imageFile in imageFiles)
{
// create new image object from file path
var image = new Image<Gray, byte>(imageFile);
images.Add(image);
// create new list of corner points
var cornerPoints = new VectorOfPoint();
corners.Add(cornerPoints);
// find chessboard corners
bool result = CvInvoke.FindChessboardCorners(image, patternSize, cornerPoints);
// some debug output
Console.WriteLine("=== " + Path.GetFileName(imageFile) + " === " + result);
if (!result)
{
continue;
}
// list points
foreach (Point cornerPoint in cornerPoints.ToArray())
{
Console.WriteLine(cornerPoint.X + ", " + cornerPoint.Y);
}
}
Console.ReadLine();
}
}
For some reason I could not get CvInvoke.DrawChessboardCorners
to execute. It did not finish executing the function in a reasonable amount of time. That's why I printed the results to Console
, which looks like this for me:
I verified a few visually in an image editor and they seem to be correct.
Pick an appropriate type that can represent a list of points and that implements IOutputArray
like VectorOfPoints
for example.
1 some say the return type is not included in a signature so calling the above a signature might be total nonsense, but you still get the idea when I say "signature".
2 now that's some useful documentation!
CvInvoke.DrawChessboardCorners works after changing VectorOfPoint
to VectorOfPointF
public class Calibration
{
static void Main(string[] args)
{
// chessboard pattern size
Size patternSize = new Size(9, 7);
// for each image, have one Image object and one VectorOfPoints
// for many images have a List of each
List<VectorOfPoint> corners = new List<VectorOfPointF>();
List<Image<Gray, Byte>> images = new List<Image<Gray, byte>>();
// get paths to image files
string[] imageFiles = Directory.GetFiles(@"C:\your\directory", "*.jpg");
// for every image
foreach (string imageFile in imageFiles)
{
// create new image object from file path
var image = new Image<Gray, byte>(imageFile);
images.Add(image);
// create new list of corner points
var cornerPoints = new VectorOfPointF();
corners.Add(cornerPoints);
// find chessboard corners
bool result = CvInvoke.FindChessboardCorners(image, patternSize, cornerPoints);
// some debug output
Console.WriteLine("=== " + Path.GetFileName(imageFile) + " === " + result);
if (!result)
{
continue;
}
// list points
foreach (Point cornerPoint in cornerPoints.ToArray())
{
Console.WriteLine(cornerPoint.X + ", " + cornerPoint.Y);
}
}
Console.ReadLine();
}
}
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