【发布时间】:2017-10-15 16:09:36
【问题描述】:
我正在尝试扫描一个恒定大小的图像并在其中找到绘制的矩形。 矩形可以有任何大小,但只有红色。
这不是问题开始的地方。
我将使用一个已经编写好的函数,稍后我将在我的代码逻辑中使用它作为伪代码调用。
Rectangle Locate(Rectangle scanArea); // 在给定的扫描区域中扫描一个矩形。
如果没有找到矩形,则返回 null。
我的逻辑是这样的:
使用Locate() 函数以完整图像大小作为参数查找第一个初始红色矩形。
现在,划分其余区域,并继续递归扫描。
该算法逻辑的要点是,您永远不会检查已检查的区域,并且您不必使用任何条件,因为 scanArea 参数始终是您之前没有扫描过的新区域(这要归功于分割技术)。
划分过程是这样进行的:当前找到的矩形的右侧区域,底部区域,左侧区域。
这是一个说明该过程的图像。 (白色虚线矩形和黄色箭头不是图像的一部分,我添加它们只是为了说明。) 如您所见,一旦找到一个红色矩形,我就会继续扫描它的右侧、底部和左侧。递归。
下面是该方法的代码:
List<Rectangle> difList=new List<Rectangle>();
private void LocateDifferences(Rectangle scanArea)
{
Rectangle foundRect = Locate(scanArea);
if (foundRect == null)
return; // stop the recursion.
Rectangle rightArea = new Rectangle(foundRect.X + foundRect.Width, foundRect.Y, (scanArea.X + scanArea.Width) - (foundRect.X + foundRect.Width), (scanArea.Y + scanArea.Height) - (foundRect.Y + foundRect.Height)); // define right area.
Rectangle bottomArea = new Rectangle(foundRect.X, foundRect.Y + foundRect.Height, foundRect.Width, (scanArea.Y + scanArea.Height) - (foundRect.Y + foundRect.Height)); // define bottom area.
Rectangle leftArea = new Rectangle(scanArea.X, foundRect.Y, (foundRect.X - scanArea.X), (scanArea.Y + scanArea.Height) - (foundRect.Y + foundRect.Height)); // define left area.
difList.Add(rectFound);
LocateDifferences(rightArea);
LocateDifferences(bottomArea);
LocateDifferences(leftArea);
}
到目前为止一切正常,它确实找到了每个红色矩形。 但有时,矩形保存为几个矩形。出于对我来说显而易见的原因: 重叠矩形大小写。
现在,在这种情况下,程序按计划找到了第一个红色区域,但是由于右侧区域仅从整个第二个区域的中间开始,因此它不会从第二个红色矩形的开头开始扫描!
以类似的方式,我可以划分区域,使底部区域从scanArea 的开头延伸到结尾,如下所示:
但是现在我们在扫描foundRect矩形左右重叠的矩形时会遇到问题,例如在这种情况下:
我只需要把每个矩形都放在一块。 我想获得与我的代码逻辑相结合的任何帮助或建议——因为它工作得很好,但我认为在递归方法中只需要一点点或两个额外的条件。我不知道该怎么做,如果能提供任何帮助,我将不胜感激。
如果有什么不清楚的地方,尽管说出来,我会尽我所能解释! 谢谢!
当然,这不是我面临的真正问题,它只是一个小演示,可以帮助我解决我正在处理的真正问题(这是一个实时互联网项目)。
【问题讨论】:
-
基本(虽然可能不是最有效的)解决方案是找到分割的矩形,然后进行一些后期处理以将它们合并在一起。例如,对于每个矩形,查看是否有另一个矩形的右上角和右下角与另一个矩形的左上角和左下角对齐。将它们合并在一起。然后找到右下角和左下角与右上角和左上角匹配的位置并将它们合并在一起。将合并的矩形放回您的集合中。然后重复直到找不到这样的匹配。
-
@pinkfloydx33 做一个嵌套循环?因为我必须将每个区域与列表中的所有其他区域进行比较.. 你是这个意思吗?
-
处理图像的副本并在找到后用背景颜色填充每个矩形,然后从第一次找到矩形的位置重新开始检查? (或者是检查图像的很大一部分 n+1 次以找到 n 个矩形太耗时?)
-
这是一个糟糕的逻辑,你最好写一个完全不同的算法。解决有缺陷的逻辑从来都不是正确的做法。它会花费更多的时间来实现,并且比从一开始就正确的算法要慢。
-
@m69 当然!我刚刚写了一个小解释
Locate函数是如何工作的:找到第一个(最左上角)红色像素,然后它继续向右扫描,然后当它没有找到更多红色像素时,它开始扫描高度,继续向下移动 - 轻松简单。由于那里使用了本机方法(例如memcmp()),它的工作速度非常快。扫描功能仅限于扫描区域参数。如果您有任何其他建议......或者如果您想查看完整功能,请随时询问!我只是不认为有瓶颈,所以我没有发布它
标签: c# algorithm image-processing computer-vision