我目前正在研究一种算法来检测台球桌的游玩区域。为此,我捕获了一幅图像,将其转换为灰度,并在其上使用了Sobel算子。现在,我想检测游戏区域作为一个盒子,4个角落位于桌子的4个角落。
检测表的边缘是相当简单的,然而,它的结果是,检测四个角落不是那么容易,因为在台球桌上有口袋。现在我只想在每条边沿上放一条线,从这些线上,我可以计算出相交,这是我的表的角。
我被困在这里,因为我还没有找到一个好的解决方案,以找到这些线在我的形象。当我使用Sobel操作符时,我可以很容易地看到它。但是,什么是检测它和计算拐角位置的好方法呢?
编辑:我添加了一些图片样本
基本图像:

灰度图像

Sobel滤波器(水平滤波器)

发布于 2015-12-13 06:08:08
对于一般的解决方案,会有很多噪音来源:栏杆周围的布的问题,铁轨上的木头纹理(或没有纹理),不同的灯光,阴影,布上的污渍,铁轨上的粉笔等等。
当颜色和光线不可靠时,当你想要找到几何物体的边缘时,最好用边缘像素而不是灰色/彩色像素来考虑。
一段时间前,我在考虑制作一个基于手机的应用程序来保存球的位置,供以后的复习,包括在线,所以我考虑了一下这个问题。虽然我可以为你当前的问题提供一些指导,但我意识到你会遇到新的问题,所以我会尝试提供一个更完整的答案。
一般性说明:
发布于 2015-12-08 15:11:27
如果颜色分割(如@Dima所建议的那样)有效,则使用等高线下面的轮廓获取blob的轮廓。然后用Douglas-Peucker算法将轮廓简化为四边形(或几个边的多边形)。你应该这样找四张桌子的边。
为了获得更高的精度,您可以通过局部搜索跨越边缘的过渡并执行直线拟合来细化边缘位置。然后把线相交得到拐角。
发布于 2015-12-08 14:32:26
下面的答案假设您已经在图像中找到了行的位置。然而,通过直接查看像素并查看它们是否处于“直线”,可以“很容易”地做到这一点。通常,如果图像是先被分解的,那么更容易检测到这一点,即旋转,这样矩形(池表)更像这样:[]而不是/=/。然后,它只是扫描像素的情况,如果有相似的颜色在它旁边,假设它们之间有一条线。
代码通过遍历在图像中找到的行来工作。每当每一行的端点在x和y坐标内的公差范围内时,它都被标记为一个角。一旦找到了拐角,我就取它们之间的平均值来找出拐角所在的位置。例如:
以10, 10结尾的水平线和从12, 12开始的垂直线将被发现为一个角,如果tolerance为2或更多。找到的拐角处在:11, 11
注意:--这只是为了找到左上角,但是很容易就能找到它们。之所以这样做,是因为在我使用它的应用程序中,首先将每个数组排序为先找到相关值的顺序更快,参见:为什么处理排序数组比未排序数组更快?。
还请注意,我的代码为每一行找到了可能不适用于您的第一个角,这主要是出于性能原因。然而,代码可以很容易地找到所有的角,所有的行,然后选择“更可能的”角或平均通过他们的所有。
还请注意,我的答案是用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。
https://stackoverflow.com/questions/34157710
复制相似问题