台球桌上的边缘检测

时间:2015-12-08 13:55:01

标签: image-processing computer-vision edge-detection

我目前正在研究一种算法来检测台球桌的比赛区域。为此,我拍摄了一张图像,将其转换为灰度图像,并在其上使用了Sobel算子。现在我想将游戏区域检测为一个盒子,其中有四个角位于桌子的四个角落。

检测桌子的边缘非常简单,但事实证明,检测4个角落不是那么容易,因为台球桌上有口袋。现在我只想在每条边线上插入一条线,从这些线条中,我可以计算出相交,这是我桌子的角落。

我被困在这里,因为我还没有想出一个很好的解决方案来在我的图像中找到这些线条。当我使用Sobel算子时,我很容易看到它。但是检测它并计算角落位置的好方法是什么?

编辑:我添加了一些示例图像

基本图片: Basic Image

灰度图像 Grayscale Image

Sobel滤镜(仅水平) Sobel Filter

4 个答案:

答案 0 :(得分:2)

如果颜色分割(由@Dima建议)有效,请使用轮廓跟踪获取blob的轮廓。然后通过Douglas-Peucker算法将轮廓简化为四边形(或几边的多边形)。你应该通过这种方式找到四个表边缘。

为了获得更高的精确度,您可以通过局部搜索其中的过渡来优化边缘位置并执行线拟合。然后与线相交以获得角落。

答案 1 :(得分:2)

对于一般解决方案,会有许多噪音来源:导轨周围的布料,导轨上的木质纹理(或无纹理),不同的光线,阴影,布料上的污渍,导轨上的粉笔以及等等。

当颜色和光线不可靠时,当您想要找到几何对象的边缘时,最好根据边缘像素而不是灰色/彩色像素进行思考。

前段时间我正在考虑制作一个基于手机的应用程序来保存球位以供以后查看,包括在线,所以我对这个问题有点了解。虽然我可以为您当前的问题提供一些指导,但我发现每一步都会遇到新的问题,所以我会尝试提供更完整的答案。

  1. 将图像转换为灰度。如果我们无法使算法在灰度级工作,我们将不可避免地遇到颜色问题。 (见下文)
  2. [待定]进行一些预处理以减少噪音。
  3. 使用Sobel或(如果必须)找到边缘点Canny。
  4. 运行霍夫线检测,但有一些注意事项和参数化,如下所述。
  5. 找到描述梯形四边形的线条。 (这可能是两个内部的四边形:一个在床上的轨道内,另一个在布/木轨边缘处的另一个略大的四边形。)
  6. (可选)使用侧袋帮助确定四边形的方向。
  7. 使用仿射变换将透视扭曲的表床映射到[感谢]已知相对尺寸的矩形。我们提前知道床的尺寸,因此您可以将扭曲的矩形重新映射到适当的矩形。 (我们现在暂时忽略一些光学效应。)
  8. 将彩色图像重新映射到经过透视校正的矩形。你可能需要调整一些球的位置。
  9. 一般说明:

    • 一般意义上的颜色过滤可能很困难。将布料简单地想象为绿色,蓝色或红色(或其他颜色)很诱人,但是当你看到实际的RGB值并尝试分离颜色时,你会开始意识到什么是色彩噩梦。是。
    • 光学失真可能会甩掉一些边缘。
    • 远短导轨可能难以检测,但是你这样做:找到两条长导轨的内线,然后在两条导轨之间垂直搜索,找到图像远端的第一个强水平边缘。那将是最短的铁路。
    • 虽然您可能希望使用手机摄像头以方便使用,但使用Kinect摄像头或类似设备(最好是较小的设备)会使问题更容易。您不仅可以同时拥有颜色数据和3D数据,而且可以消除一些照明问题,因为深度数据不依赖于可见光。
    • 对于您的应用,请考虑将导轨边缘的搜索区域限制为透视变形矩形。用户可能能够调整搜索区域。这可以大大简化处理过程,并且可以帮助您解决问题,如果表格没有很好地点亮(可能是这种情况)。

答案 2 :(得分:1)

以下答案假设您已经找到了图像中线条的位置。然而,这可以很容易地完成"通过直接查看像素并查看它们是否在"行"。通常,如果首先对图像进行了校正,则更容易检测到这一点,即旋转,因此矩形(池表)更像是:[]而不是像/=/。然后它只是一个扫描像素的情况,如果它们旁边有相似的颜色,假设它们之间有一条线。

代码通过循环遍历图像中找到的线来工作。每当每条线的终点落在xy坐标内的公差范围内时,它就会被标记为一个角。一旦发现了角落,我会取它们之间的平均值来找到角落所在的位置。例如:

如果10, 10为2或更多,则会发现以12, 12结尾的水平线和从tolerance开始的垂直线为角。找到的角落位于: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

答案 3 :(得分:0)

台球桌的游戏区域通常具有独特的颜色,如绿色或蓝色。我会先尝试一种基于颜色的分割方法。 MATLAB中的Color Thresholder应用程序为您提供了一种尝试不同颜色空间和阈值的简便方法。