经过一些处理后,我有了这个二进制图像:
我想删除未闭合的曲线,即左上角和右下角曲线。你能建议我做这个的算法吗?感谢。
答案 0 :(得分:6)
正如@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()
答案 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);