如何使用FindChessboardCorners

时间:2015-04-10 08:52:51

标签: c# emgucv opencv3.0

我正在使用新的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速度更快,时间在我的应用程序中是个大问题。

1 个答案:

答案 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,这对我来说是这样的:

enter image description here

我在图像编辑器中以视觉方式验证了一些,但它们似乎是正确的。

TL;博士

选择一个适当的类型,可以代表点数列表,并实现IOutputArray,例如VectorOfPoints

1 有人说回复类型不包含在签名中,因此调用上面的签名可能完全是胡说八道,但是当我说“签名”

2 现在这是一些有用的文档!