以下答案假设您已经找到图像中线条的位置。然而,这可以通过直接查看像素并查看它们是否在“线”中来“轻松”完成。通常,如果图像也已先进行了校正,即旋转,因此矩形(台球桌)更像这样:[] 而不是/=/,通常更容易检测到这一点。那么这只是扫描像素的情况,如果旁边有类似颜色的像素,假设它们之间有一条线。
代码通过循环遍历图像中的行来工作。只要每条线的端点落在x 和y 坐标内的公差范围内,它就会被标记为角。一旦找到拐角,我就取它们之间的平均值来找出拐角所在的位置。例如:
如果tolerance 为2 或更多,则以10, 10 结束的水平线和以12, 12 开始的垂直线将被发现是角。找到的角落将在:11, 11
注意:这只是为了找到左上角,但可以很容易地适应所有这些。这样做的原因是因为在我使用它的应用程序中,首先将每个数组排序为首先找到相关值的顺序会更快,请参阅:Why is processing a sorted array faster than an unsorted array?。
另外请注意,我的代码会为每一行找到第一个角,这可能对您不适用,这主要是出于性能原因。然而,代码可以很容易地调整为找到所有线的所有角,然后选择“更有可能”的角或对它们进行平均。
还要注意我的答案写在C#。
private IEnumerable<Point> FindTopLeftCorners(IEnumerable<Line> horizontalLines, IEnumerable<Line> verticalLines)
{
List<Point> TopLeftCorners = new List<Point>();
Line[] laHorizontalLines = horizontalLines.OrderBy(l => l.StartPoint.X).ThenBy(l => l.StartPoint.Y).ToArray();
Line[] laVerticalLines = verticalLines.OrderBy(l => l.StartPoint.X).ThenBy(l => l.StartPoint.Y).ToArray();
foreach (Line verticalLine in laVerticalLines)
{
foreach (Line horizontalLine in laHorizontalLines)
{
if (verticalLine.StartPoint.X <= (horizontalLine.StartPoint.X + _nCornerTolerance) && verticalLine.StartPoint.X >= (horizontalLine.StartPoint.X - _nCornerTolerance))
{
if (horizontalLine.StartPoint.Y <= (verticalLine.StartPoint.Y + _nCornerTolerance) && horizontalLine.StartPoint.Y >= (verticalLine.StartPoint.Y - _nCornerTolerance))
{
int nX = (verticalLine.StartPoint.X + horizontalLine.StartPoint.X) / 2;
int nY = (verticalLine.StartPoint.Y + horizontalLine.StartPoint.Y) / 2;
TopLeftCorners.Add(new Point(nX, nY));
break;
}
}
}
}
return TopLeftCorners;
}
其中Line 是以下class:
public class Line
{
public Point StartPoint { get; private set; }
public Point EndPoint { get; private set; }
public Line(Point startPoint, Point endPoint)
{
this.StartPoint = startPoint;
this.EndPoint = endPoint;
}
}
而_nCornerTolerance 是可配置数量的int。