6

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

在此处输入图像描述

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

4

3 回答 3

8

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

  1. 用白色填充图像 - 这可以消除您的问题非闭合线,还可以消除您想要的对象的边界。
  2. 腐蚀图像,然后反转它
  3. 与原始图像的图像 - 从而恢复边界。

输出:

在此处输入图像描述

代码在 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()
于 2013-02-18T14:12:29.977 回答
5

您正在寻找洪水填充:http ://en.wikipedia.org/wiki/Flood_fill

于 2013-02-18T13:07:15.173 回答
0

我对一个想法进行了一些尝试,尽管从长远来看,这不是最有效的方法。我将图像转换为 300x300 字符的数组,它似乎在这方面效果很好。我对opencv不熟悉。

这个想法是遍历每个像素,看看它是否标记了一行的结尾——如果是,则将该像素设为黑色。重复直到图片没有变化。

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

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);
于 2013-02-18T14:07:26.743 回答