【问题标题】:How do I fix eroded rectangles?如何修复被侵蚀的矩形?
【发布时间】:2011-06-17 23:39:06
【问题描述】:

基本上,我有这样的图像

或者在同一张图片中有多个矩形。矩形是完全黑色和白色的,有“脏”的边缘和凹槽,但很容易判断它们是矩形。更准确地说,它们是图像掩码。白色区域是图像中要“单独放置”的部分,但黑色部分是双色调的。

我的问题是,我如何用这个退化的矩形制作一个漂亮而清晰的矩形?我是一个 Python 人,但我必须使用 Qt 和 C++ 来完成这项任务。最好不使用其他库。

谢谢!

【问题讨论】:

  • 矩形是否总是与外部矩形对齐,或者您可能有(例如)一个旋转 45 度的正方形,形成菱形形状(即使它仍然有方角和直边) ?
  • 虽然不是针对c++,但how to detect blobs and crop them in png files上的一些答案可能与这个问题非常相关。
  • 嗯,这是一个简单的案例;)我的目标是单独找到所有形状的边界框(它们主要是矩形和椭圆形,但偶尔会得到随机形状)以最小化图像腐蚀。
  • @Jerry Coffin,它们都是大的、白色的、不相交的矩形,几乎没有旋转。
  • @Blender 关于您最后的评论,不同的几何形状需要不同的算法。检测矩形的算法不会检测到椭圆(椭圆),至少不是最佳算法。因此,如果您对其他几何形状有要求,我建议更新问题!

标签: c++ qt image-processing qt4 masking


【解决方案1】:

如果包含所有非黑色像素的边界框可以做你想做的事,这应该可以解决问题:

int boundLeft = INT_MAX;
int boundRight = -1;
int boundTop = INT_MAX;
int boundBottom = -1;
for(int y=0;y<imageHeight;++y) {
    bool hasNonMask = false;
    for(int x=0;x<imageWidth;++x) {
        if(isNotMask(x, y)) {
            hasNonMask = true;
            if(x < boundLeft) boundLeft = x;
            if(x > boundRight) boundRight = x;
        }
    }
    if(hasNonMask) {
        if(y < boundTop) boundTop = y;
        if(y > boundBottom) boundBottom = y
    }
}

如果结果大小为负,则图像中没有非掩码像素。代码可以更优化,但我还没有喝足够的咖啡。 :)

【讨论】:

  • 是的!这比包含 OpenCV(停止 svn)要少得多!我会回帖确认它是否有效。
  • 它有效!我刚刚修复了那些++y 语句并添加了一些东西,但它有效。并且不需要 OpenCV!谢谢!
  • 糟糕。知道它不仅仅是未优化的。抱歉打错了,很高兴它有效。
【解决方案2】:

通常你会通过反复扩张和侵蚀面具来做到这一点。我认为 qt 没有为此提供预制功能,因此如果您不想使用库,您可能必须自己实现它们 - http://ostermiller.org/dilate_and_erode.html 提供了有关如何实现这些功能的信息。

【讨论】:

  • 我用 GIMP 试过了,它似乎摆脱了巨大凿痕周围的噪音。这更近了一步:D!现在我将如何填补这些凿痕?是时候再 Google 一下了……
  • 如果你做的次数足够多,或者选择更大的半径,它最终会填满那些凿痕。
  • 我刚刚注意到 gimp 不像我链接到的页面那样。您需要使其仅切换像素的 4 个最近邻居,而不是仅与像素共享一个角的 4 个。
【解决方案3】:

目前,我们假设它们都应该是没有旋转的矩形。在这种情况下,您应该能够使用一种非常简单的方法。从位图边缘的每个像素开始,开始向内采样像素,直到遇到过渡。记录每个过渡到边缘的距离(如果有的话)。一旦你从每条边完成了这项工作,你基本上就“投票”了——从那个边最常发生的距离就是你认为矩形的那个边。如果矩形真的是对齐的,那应该是大部分距离。

如果相反,您看到许多距离频率几乎相等,则可能是矩形旋转(或至少一个边旋转)。在这种情况下,您可以将一侧分成两半(例如)并重复。一旦您在每个区域中达到了大部分同意距离的点,您可以(尝试)在它们之间进行线性插值以给出一条直线(并且限制最小区域大小将限制最大旋转 - 如果您得到在未达成一致的情况下达到某种尺寸,您看到的是凿子,而不是矩形边缘)。同样,如果您有一个区域(或多个区域)与其余区域不完全吻合,也不适合一条线,您可能也应该忽略它——同样,您可能正在查看凿孔,而不是预期的优势。

【讨论】:

  • 谢谢!这给了我一个好主意,这是你算法的一个更简单的版本(我稍后会使用你的。它非常适合几何形状):从左边缘开始,然后“拍摄”线条,直到它们碰到一个白色像素。平均这些距离(不包括异常值,例如不会“击中”任何白色像素的线条),并且您拥有矩形与图像一侧的正确距离。对其余的方向重复(如果你有一个大凿子,这将失败)。
  • @Blender 好方法。我认为如果您使用中位数而不是平均值,您将解决异常值的问题。
  • 我想我会接受@Stephen Chu 的回答。它做我想要的(我不想切掉小像素,因为这可能会给彩色图像带来双色调边框),而且它在概念上很简单。但是您的方法将用于其他复杂的形状!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多