如何删除二进制图像中未闭合的曲线?

时间:2013-02-18 13:02:40

标签: opencv

经过一些处理后,我有了这个二进制图像:

enter image description here

我想删除未闭合的曲线,即左上角和右下角曲线。你能建议我做这个的算法吗?感谢。

3 个答案:

答案 0 :(得分:6)

正如@John Zwinck所提到的,这可以使用floodfill完成,但我认为你的问题是你想要回到原始的黑色背景,并保留封闭形状的轮廓。虽然您可以使用contours来解决这个问题,但这是一个相当简单的方法,它将从图像中删除所有非闭合和未闭合的线段,即使它们连接到闭合的形状,但保留边缘封闭的曲线。

  1. 使用白色填充图像 - 这会删除您的问题非闭合线,但也会删除所需对象的边框。
  2. 侵蚀图像,然后将其反转
  3. 和原始图像的图像 - 从而恢复边框。
  4. 输出:

    enter image description here

    代码在python中,但应该很容易转换为通常的C ++ cv2用法。

    import cv2
    import numpy as np
    
    im = cv2.imread('I7qZP.png',cv2.CV_LOAD_IMAGE_GRAYSCALE)
    im2 = im.copy()
    mask = np.zeros((np.array(im.shape)+2), np.uint8)
    cv2.floodFill(im, mask, (0,0), (255))
    im = cv2.erode(im, np.ones((3,3)))
    im = cv2.bitwise_not(im)
    im = cv2.bitwise_and(im,im2)
    cv2.imshow('show', im)
    cv2.imwrite('fin.png',im)
    cv2.waitKey()
    

答案 1 :(得分:5)

您正在寻找Flood Fill:http://en.wikipedia.org/wiki/Flood_fill

答案 2 :(得分:0)

我有一个想法的游戏,虽然它远远不是最有效的方法。我将图像转换为300x300字符的数组,它似乎很好用。我不熟悉opencv。

这个想法是通过每个像素,看看它是否标志着一条线的结束 - 如果是这样,那么这个像素是黑色的。重复,直到图片没有变化。

我用来将像素识别为一行的标准是注意该像素循环周围的黑白变化的数量。如果少于4个更改,则它是一行的结尾。如果线条厚度超过1像素,则无效。我可能想出更好的东西。它似乎适用于提供的图片。

do {
   res = 0;
   for (i = 1; i < 299; i++) {
      for (j = 1; j < 299; j++) {
         if (image[i][j] != 0) {
            count = 0;

            if (image[i-1][j-1] != image[i-1][j+0]) count++;
            if (image[i-1][j+0] != image[i-1][j+1]) count++;
            if (image[i-1][j+1] != image[i+0][j+1]) count++;
            if (image[i+0][j+1] != image[i+1][j+1]) count++;
            if (image[i+1][j+1] != image[i+1][j+0]) count++;
            if (image[i+1][j+0] != image[i+1][j-1]) count++;
            if (image[i+1][j-1] != image[i+0][j-1]) count++;
            if (image[i+0][j-1] != image[i-1][j-1]) count++;

            if (count < 4) {
               image[i][j] = 0;
               res = 1;
            }
         }
      }
   }
} while (res);