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

时间:2014-03-06 18:05:07

标签: c# sorting opencv

我有一个关于从棋盘中找到角落的问题。 我正在使用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

参见示例2 all pictures

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

在拉直点上工作。确定图像的斜率,例如通过取右上角和左上角的差值。见Rotation (mathematics)。你也可以采取-diff.Y(减去因为我们想要向后旋转)和diff.X来获取罪。采用这些“错误”值的效果将导致缩放。

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

因为它们没有,所以围绕坐标使它们全部为整数。将这些整数坐标按y然后按x排序应该可以得到您想要的顺序。这是因为同一水平线上的点现在确实具有相同的y值。事实并非如此。由于它们可能都具有不同的y坐标,因此只有x的第二次排序才会产生影响。

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

答案 1 :(得分:1)

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

为更清楚起见,将订阅四边形的索引的顺序添加为0、1、2、3。

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

  • topLeft
  • topRight
  • bottomLeft
  • bottomRight

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

为简化排序,您可能希望将列表“重塑”为一个数组,该数组适合您在第一位置为findChessBoardCorners提供的象棋图案。 9x9。在python numpy中,有一个我不知道如何在C#中完成的功能。

example 1 example 2