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

Opencv 如何删除二进制图像中未闭合的曲线?,opencv,Opencv,经过一些处理后,我得到了这个二值图像: 我要删除未闭合的曲线,即左上角和右下角曲线。你能告诉我做这个的算法吗?谢谢。您正在寻找洪水填充:我有一个想法,尽管从长远来看,这不是最有效的方法。我将图像转换为一个300x300个字符的数组,看起来效果不错。我不熟悉opencv 我们的想法是通过每个像素,看看它是否标志着一行的结束-如果是这样,使该像素黑色。重复此操作,直到图片没有变化 我用来识别一个像素作为一行的结尾的标准是注意该像素的循环周围黑白变化的数量。如果更改少于4次,则为一行的结尾。如果线的

经过一些处理后,我得到了这个二值图像:


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

您正在寻找洪水填充:

我有一个想法,尽管从长远来看,这不是最有效的方法。我将图像转换为一个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);
do{
res=0;
对于(i=1;i<299;i++){
对于(j=1;j<299;j++){
如果(图像[i][j]!=0){
计数=0;
if(image[i-1][j-1]!=image[i-1][j+0])计数++;
如果(图像[i-1][j+0]!=图像[i-1][j+1])计数++;
如果(图像[i-1][j+1]!=图像[i+0][j+1])计数++;
如果(图像[i+0][j+1]!=图像[i+1][j+1])计数++;
如果(图像[i+1][j+1]!=图像[i+1][j+0])计数++;
如果(图像[i+1][j+0]!=图像[i+1][j-1])计数++;
if(image[i+1][j-1]!=image[i+0][j-1])计数++;
如果(图像[i+0][j-1]!=图像[i-1][j-1])计数++;
如果(计数<4){
图像[i][j]=0;
res=1;
}
}
}
}
}while(res);

正如@John Zwinck提到的,这可以使用
泛光填充来完成,但我想你的问题是你想回到原来的黑色背景,并保留封闭形状的轮廓。虽然您可以使用
等高线
来解决这个问题,但这里有一个相当简单的方法,可以从图像中删除所有非闭合和非闭合线段,即使它们附着到闭合形状,但保留闭合曲线的边

  • 用白色填充图像-这将删除有问题的非闭合线,以及所需对象的边界
  • 腐蚀图像,然后将其反转
  • 和原始图像的图像-从而恢复边界
  • 输出:

    代码位于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()
    

    我知道“泛光填充”可以用于用给定颜色填充两条闭合曲线。但是你能告诉我(也许有一些代码)如何使用它来删除未闭合的曲线吗?从外部边界开始,然后从那里洪水泛滥。这将抹去未闭合的曲线,留下闭合的曲线。步骤由fraxel的答案提供。但是谢谢你的回答。StackOverflow不是这个问题的合适位置。我们不会为您编写代码。你需要自己编写代码,如果你不确定为什么有些东西不能按预期工作,那么在发布代码时解释一下你期望它做什么,以及它实际在做什么,包括所有错误消息。看。@LightnessRacesinOrbit我不是要代码,我是要一个算法,让我来写代码。虽然如果有人建议一个带有代码的算法,我会更高兴。所以,如果最后的问题仅限于那些在问题中使用的标记中得分不太低(可能是50分左右)的问题,那将是一个更好的地方。当然,这个问题的标签很差,但这是另一个问题。以不具建设性的方式关闭它是完全不正确的,充其量它可以作为一个重复关闭,我怀疑是这样的(尽管我没有搜索)。