我正在使用新的EmguCV 3.0.0 alpha来检测带网络摄像头的棋盘,并对角矩阵有一个理解问题。
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);
}
棋盘将被检测到并显示正确!
但是,角矩阵的大小必须有多大,我如何提取角位置?
我在互联网上找到的所有样本都使用旧版本的EmguCV,现在有完全不同的语法。我会使用较旧的版本,但更新的alpha速度更快,时间在我的应用程序中是个大问题。
答案 0 :(得分:5)
CvInvoke.FindChessboardCorners
Method有这个签名 1 :
public static bool FindChessboardCorners(
IInputArray image,
Size patternSize,
IOutputArray corners,
CalibCbType flags = CalibCbType.Default|CalibCbType.AdaptiveThresh|CalibCbType.NormalizeImage
)
第三个参数是IOutputArray
2 类型。我不明白为什么他们引入了这些超级通用的输入/输出接口,这些接口是由不能互换使用的各种类实现的。
你是对的,Matrix
类确实实现了该接口(通过超类CvArray
),因此你的代码编译。
但是,CvInvoke.FindChessboardCorners
应该返回几个点(取决于模式的大小)。我用Google搜索了实现IOutputArray
并找到VectorOfPoints
的类。这对我来说更有意义,比使用Matrix
更有意义。
我将一个用于校准的小型控制台应用程序混合在一起,从目录中读取所有图像文件并检测其中的角落,因为对我来说,预先捕获图像更有意义。
那应该给你一个起点:
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();
}
}
出于某种原因,我无法执行CvInvoke.DrawChessboardCorners
。它没有在合理的时间内完成执行功能。这就是为什么我将结果打印到Console
,这对我来说是这样的:
我在图像编辑器中以视觉方式验证了一些,但它们似乎是正确的。
选择一个适当的类型,可以代表点数列表,并实现IOutputArray
,例如VectorOfPoints
。
1 有人说回复类型不包含在签名中,因此调用上面的签名可能完全是胡说八道,但是当我说“签名”
2 现在这是一些有用的文档!