如何对找到的棋盘角进行排序?

Posted

技术标签:

【中文标题】如何对找到的棋盘角进行排序?【英文标题】:How to sort found chessboard corners? 【发布时间】:2014-03-06 18:05:07 【问题描述】:

我有一个关于从棋盘上对找到的角进行排序的问题。 我正在使用 OpenCVSharp 在 C# 中编写我的程序。

我需要对找到的角进行排序,这些角是由 X 和 Y 描述的点。 这是我的代码的一部分:

...
CvPoint2D32f[] corners;
bool found = Cv.FindChessboardCorners(gray, board_sz, out corners, out corner_count,
    ChessboardFlag.NormalizeImage | ChessboardFlag.FilterQuads);
Cv.FindCornerSubPix(gray, corners, corner_count, new CvSize(11,11), new CvSize(-1,-1),
    Cv.TermCriteria(CriteriaType.Epsilon | CriteriaType.Iteration, 30, 0.1));

Cv.DrawChessboardCorners(img1, board_sz, corners, found);
...

之后我在 ImageBox 中显示找到的角:

在all pictures看到良好的秩序

这是我一直需要的角的顺序,但是当我稍微旋转棋盘时 - 发现角的变化如下:

在all pictures中查看不良订单

我需要这些点的顺序相同(如图 1 所示),所以我决定使用:

var ordered = corners.OrderBy(p => p.Y).ThenBy(p => p.X);
corners = ordered.ToArray();

但它不像我想要的那样工作:

在 all pictures

中查看错误结果 1

在 all pictures

中查看错误结果 2

重点是我的棋盘不会旋转太多,只是旋转一点角度。 第二点是角必须从棋盘左上角的第一个白色方块开始排列。 我知道,基点 (0,0) 位于图像的左上角,Y 的正值在图像底部的方向上增加,X 的正值在右侧的方向上增加图像。

我正在编写程序以获得此排序(这些图片是在图片编辑器中编辑的):

见all pictures中的示例1

见all pictures中的示例2

感谢您的帮助。

【问题讨论】:

我将取棋盘的中心点并在中心周围的一个象限中找到每个点。 不幸的是,所有链接都已损坏。类似问题请见wiki.bitplan.com/index.php/PlayChessWithAWebCam/… 【参考方案1】:

请在下面找到一些示例,了解 OpenCV 的 findChessboardCorners 如何返回角点列表以及 drawChessboardCorners 如何显示角点。

为更清楚起见,下标四边形的索引顺序添加为 0,1,2,3。

基本上有 4 种可能的结果旋转导致初始红色标记为:

左上角 右上 左下角 右下角

因此,当您想求助时,您可以考虑这些知识并相应地更改索引的顺序。好消息是,通过这种方法,您不必查看所有 x,y 值。比较列表中的第一个和最后一个值就足以找出轮换是什么。

为了简化排序,您可能希望将列表“重塑”为适合您提供给 findChessBoardCorners 的国际象棋模式的数组,例如9x9。在 Python numpy 中有一个函数,我不知道如何在 C# 中完成。

【讨论】:

查看wiki.bitplan.com/index.php/PlayChessWithAWebCam/…了解更多详情和其他问题的链接【参考方案2】:

处理拉直的点。确定图像的斜率,例如通过获取右上点和左上点的差异。见Rotation (mathematics)。除了取 cos,您还可以取 -diff.Y(减号,因为我们想向后旋转)和 diff.X 为 sin。采用这些“错误”值的效果将导致缩放。

现在确定这些拉直点的 x 和 y 的最小值和最大值。您可以从中获得两条信息:1)与坐标原点的偏移量。 2) 板的尺寸。现在重新缩放变换点,使它们的坐标在 0.0 和 8.0 之间。现在,如果图像是完美的,所有点的坐标都应该是整数值。

因为它们没有,所以将坐标四舍五入以使它们全部为整数。按 y 然后按 x 对这些整数坐标进行排序应该会产生您想要的顺序。这是因为同一水平线上的点现在实际上具有相同的 y 值。这不是以前的情况。由于它们可能都有不同的 y 坐标,因此只有第二次按 x 排序有效果。

为了对原始点进行排序,将转换后的点和原始点放在同一个类或结构中(例如元组)并一起排序。

【讨论】:

@WolfgangFahl,五年多之后,它仍然是唯一的答案。让它变得更好! 我很想见wiki.bitplan.com/index.php/PlayChessWithAWebCam/…

以上是关于如何对找到的棋盘角进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

对对象数组进行排序角打字稿

极角排序

极角排序

Hdu5032 极角排序+树状数组

JAVA-初步认识-第五章-数组-常见操作-排序的性能问题

如何选择然后对 MongoDB 文档进行排序,然后找到下一个要挖掘的文档?