5

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

4

2 回答 2

5

CvInvoke.FindChessboardCorners方法具有此签名1

public static bool FindChessboardCorners(
    IInputArray image,
    Size patternSize,
    IOutputArray corners,
    CalibCbType flags = CalibCbType.Default|CalibCbType.AdaptiveThresh|CalibCbType.NormalizeImage
)

第三个参数是类型2。我不明白他们为什么要引入这些由不能互换使用的各种类实现的超通用输入/输出接口。IOutputArray

您是对的,Matrix该类确实实现了该接口(通过 super class CvArray),因此您的代码可以编译。但是,CvInvoke.FindChessboardCorners应该返回几个点(取决于模式的大小)。我搜索了实现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,这对我来说是这样的:

在此处输入图像描述

我在图像编辑器中直观地验证了一些,它们似乎是正确的。

tl;博士

选择一个合适的类型,它可以表示一个点列表并实现IOutputArray类似VectorOfPoints的例子。


1有人说返回类型不包含在签名中,因此将上述称为签名可能完全是胡说八道,但是当我说“签名”时,您仍然会明白。

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

于 2015-10-06T14:57:41.570 回答
1

CvInvoke.DrawChessboardCorners 更改VectorOfPointVectorOfPointF

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();
    }
}
于 2022-01-07T19:48:41.117 回答