我可以成功阈值图像并在图像中找到边缘。我正在努力的是试图准确地提取黑色边缘的角度。
我目前正在使用黑色边缘的极值点并使用atan2函数计算角度,但由于混叠,根据您选择的点,角度可能会出现一定程度的变化。是否有可靠的可编程方式选择点来计算角度?
示例图片:
例如,Gimp Measure工具角度为3.12°,
答案 0 :(得分:3)
如果你正在编写自己的库,那么为这个问题创建一个强大的解决方案将允许你开发几个独立的代码块,你可以串起来解决其他问题。我假设您想在任意旋转下,在变化的光照条件下,在图像噪声存在的情况下找到棋盘角,有一点非线性枕形/桶形失真,等等。
尽管有一些简单的基于内核的技术可以将整个像素作为边缘像素进行查找,但在使用填充多边形时,您会希望使用能够找到具有亚像素精度的边缘的算法,以便您可以执行准确的线条拟合。即使从黑色方块到白色方块的渐变穿过几个像素," true"边缘将在某个子像素点处找到,很可能不是您通过手动点击猜测的点。
我试图在这篇较旧的SO帖子中提供边缘发现的简单摘要: what is the relationship between image edges and gradient?
对于像你这样的问题,一个强大的解决方案是沿着亚像素精度找到沿暗到光过渡的边缘点,然后将线拟合到边缘点,并使用线角度。如果您正在处理真实的相机图像,并且图像中存在未校正的径向失真,则测量精度存在一些潜在问题,但我们会忽略这些问题。
如果要找到边缘的精确拟合,那么在垂直于该边缘的方向上扫描子像素边缘会很棒。这预先假定我们对边缘方向有一些合理的估计。我们可以首先找到边缘方向的粗略估计,然后执行精确的线拟合。
下面的算法似乎有太多步骤,但我的目的是指出如何提供强大的解决方案。
然后,您将遍历blob列表并为每个blob执行以下操作:
该算法独立地为每个黑色棋盘方块找到角度。对于这一个应用程序来说可能有点过分,但是如果你正在开发一个库,那么它可能会给你一些关于要实现哪些子算法以及如何构建它们的想法。例如,该算法将依赖于这些技术的实现:
所有这一切,如果你愿意接受精确度的轻微损失,并且如果你知道图像没有受到径向扭曲等的影响,并且如果你只是需要找到角度由所有检查板边缘定义的平行线,然后您可以尝试..
还有其他技术不太准确但更容易实现:
依此类推。当您正在开发库并创建可靠的独立功能实现时,您可以将它们组合在一起以创建特定于应用程序的解决方案,您可能会发现强大的解决方案依赖于比您猜测的更多的步骤,但是它还会更清楚每个增量步骤的故障模式,以及如何解决该故障模式。
答案 1 :(得分:0)
我可以问一下,您使用什么C ++库来编写代码?
Jerry是对的,如果你真的对图像应用了一个阈值,它将是2位,黑色或白色。你应用的是一种限制器。
您可以通过应用您可能使用的限制器然后将所有非白色像素变为黑色来制作阈值功能(如果您自己编码图像处理)。如果你有正确的设置,应该隔离正方形,你就可以计算出角度。
完成此操作后,您可以使用路径查找算法查找某些边缘,任何边缘都可以。如果您找到一个或多或少的直线路径,您可以像现在一样使用极值点来确定角度。由于棋盘旋转仅在90度内相关,因此您的角度应为模90度或pi超过2弧度。
答案 2 :(得分:0)
我不确定它(接近任何地方) 正确的答案,但我的立即反应将是两次阈值:一次除了黑色之外的任何东西都被视为白色,一次除外白色被视为黑色。
找出每个角度,然后在两个角度之间进行插值。
答案 3 :(得分:0)
你的问题很少有解决方案,但都有一个非常重要的问题你似乎忽略了。注意:当您尝试在图像中进行几何计算时,您使用的点必须尽可能远离另一个。你在一个方格内拿2分。这些点彼此非常接近,因此点的像素位置的轻微误差导致角度的大误差。当图像中有多个正方形时,为什么只使用一个正方形? 以下是一些解决方案:
(gx,gy)
,计算每个像素atan(gy,gx)
中的渐变角度,并制作角度的直方图。在3°和93°附近将有2个显着的峰值。只需在直方图中搜索最大值即可找到峰值。即使您在图像中有很多噪点,即使使用了防眩光和jpg瑕疵,即使图像上有其他图形,这也会起作用。但请记住,在计算导数之前,必须对图像进行平滑处理。