经过一些处理,我有这个二进制图像:
我想删除未闭合的曲线,即左上角和右下角曲线。你能建议我这样做的算法吗?谢谢。
正如@John Zwinck 提到的,这可以使用 来完成floodfill
,但我认为您的问题是您想要返回原始的黑色背景,并保留闭合形状的轮廓。虽然您可以使用它contours
来解决这个问题,但这是一种相当简单的方法,它将从图像中删除所有非闭合和未闭合的线段,即使它们附加到闭合形状,但保留闭合曲线的边缘。
输出:
代码在 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()
您正在寻找洪水填充:http ://en.wikipedia.org/wiki/Flood_fill
我对一个想法进行了一些尝试,尽管从长远来看,这不是最有效的方法。我将图像转换为 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);