Image processing 池表的边缘检测
我目前正在研究一种算法来检测台球桌的游戏区域。为此,我拍摄了一幅图像,将其转换为灰度,并对其使用了Sobel操作符。现在,我想将游戏区域检测为一个长方体,其中4个角位于桌子的4个角中 检测桌子的边缘非常简单,但是,检测4个角却不是那么容易,因为台球桌上有口袋。现在我只想在每个边上拟合一条线,从这些线,我可以计算出相交点,这是我桌子的角 我被困在这里,因为我还不能想出一个好的解决方案,在我的图像中找到这些线条。当我使用Sobel运算符时,我可以很容易地看到它。但是,有什么好方法可以检测它并计算角点的位置呢 编辑:我添加了一些示例图像 基本图像: 灰度图像 Sobel过滤器(仅水平)Image processing 池表的边缘检测,image-processing,computer-vision,edge-detection,Image Processing,Computer Vision,Edge Detection,我目前正在研究一种算法来检测台球桌的游戏区域。为此,我拍摄了一幅图像,将其转换为灰度,并对其使用了Sobel操作符。现在,我想将游戏区域检测为一个长方体,其中4个角位于桌子的4个角中 检测桌子的边缘非常简单,但是,检测4个角却不是那么容易,因为台球桌上有口袋。现在我只想在每个边上拟合一条线,从这些线,我可以计算出相交点,这是我桌子的角 我被困在这里,因为我还不能想出一个好的解决方案,在我的图像中找到这些线条。当我使用Sobel运算符时,我可以很容易地看到它。但是,有什么好方法可以检测它并计算角点
台球桌的游戏区域通常有一种独特的颜色,如绿色或蓝色。我会先尝试一种基于颜色的分割方法。MATLAB中的应用程序为您提供了一种尝试不同颜色空间和阈值的简单方法。以下答案假设您已经找到图像中线条的位置。然而,这可以通过直接观察像素并查看它们是否在一条“线”中“轻松”完成。通常,如果图像也已先进行了倾斜(即旋转),则更容易检测到此问题,因此矩形(池表)更像这样:
[]
,而不是像/=/
。然后,它只是扫描像素的一种情况,如果旁边有颜色相似的像素,则假设它们之间有一条线
代码通过在图像中找到的行上循环来工作。当每条线的端点位于x
和y
坐标的公差范围内时,它被标记为一个角。一旦找到角点,我取它们之间的平均值来找到角点所在的位置。例如:
如果公差为2或更多,则在10,10
处结束的水平线和在12,12
处开始的垂直线将被发现为一个角。找到的角将位于:11,11
注意:这仅用于查找左上角,但可以轻松调整以查找所有左上角。之所以这样做,是因为在我使用它的应用程序中,首先将每个数组排序为先找到相关值的顺序更快,请参见:
还要注意,我的代码为每一行查找第一个角点,这可能不适用于您,这主要是出于性能原因。然而,代码可以很容易地进行调整,以找到所有线条的所有角点,然后选择“更有可能”的角点或对它们进行平均
另外请注意,我的答案是用C.
写的
而\u nCornerTolerance
是一个可配置量的int
。如果颜色分割(如@Dima所建议)起作用,请使用轮廓跟踪获得斑点的轮廓。然后使用道格拉斯-佩克算法将轮廓简化为四边形(或少数边的多边形)。你应该这样找到桌子的四条边
为了获得更高的精度,可以通过局部搜索边缘上的过渡来优化边缘位置,并执行直线拟合。然后将线相交以获得角。对于一般解决方案,会有许多噪声源:钢轨周围的布料问题、钢轨上的木材纹理(或无纹理)、不同的照明、阴影、布料上的污渍、钢轨上的粉笔等
当颜色和照明不可靠时,当您想要找到几何对象的边缘时,最好考虑边缘像素,而不是灰度/颜色像素
不久前,我曾考虑制作一款基于手机的应用程序,将球的位置保存起来,以备日后查看,包括在线查看,因此我对这个问题进行了一些思考。虽然我可以为您当前的问题提供一些指导,但我觉得您在每一步都会遇到新问题,因此我将尝试提供更完整的答案
将图像转换为灰度。如果我们不能让算法在灰度下工作,我们将不可避免地遇到颜色问题。(见下文)
[TBD]进行一些预处理以减少噪音
使用Sobel或(如果必须)Canny查找边点
运行Hough线检测,但有一些警告和参数化,如下所述
找出梯形四边形所描述的线。(这可能是两个内部四边形:一个在床上的栏杆内,另一个稍大的四边形在顶部的布/木栏杆边缘。)
(可选)使用侧袋帮助确定四边形的方向
使用仿射变换将透视扭曲的桌子床映射到[谢天谢地]已知相对尺寸的矩形。我们预先知道床的尺寸,所以您可以将扭曲的矩形重新映射到适当的矩形。(我们现在将忽略一些光学效果。)
将彩色图像重新映射到透视校正矩形。你可能需要调整一些球的位置
一般说明:
- 从一般意义上讲,按颜色过滤可能很困难。人们很容易将布料简单地想象为绿色、蓝色或红色(或其他颜色),但当你看到实际的RGB值并尝试分离颜色时,你就会开始意识到使用颜色是多么可怕李>
- 光学畸变可能会使某些边缘脱落
- 较短的轨道可能很难检测,但您可以这样做:找到两条长轨道的内线,然后在两条轨道之间垂直搜索第一条轨道
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;
}
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;
}
}