如何从文档中删除图像的边框(如 MNIST 手写字符)?

How to remove borders from images taken from document (like MNIST handwritten chars)?

我想提取这样写在盒子里的手写字符。

我正在提取宽度为 29 像素的正方形,这会给我这样的图像。

要正确识别字符,单个字符图像需要非常干净。像这样,

我在做什么,

  1. 计算水平和垂直投影 每张图片。
  2. 遍历两个数组的每个元素。如果projection 的值大于某个阈值,则表示没有遇到边界。它删除了边框周围的空白。

  3. 然后在图像中找到轮廓。

  4. 如果轮廓的面积大于某个阈值。获取边界矩形并裁剪它。

但问题是,这个方法不是那么准确。在某些情况下,它工作正常,但在大多数情况下,如果失败得很惨。 它会生成像

这样的图像

投影值也非常特定于此图像(或更接近此图像的图像)。它不能很好地概括。

有没有其他方法可以很好地应对这种情况?

代码,

char = cv2.imread(image)
char_gray = cv2.cvtColor(char, cv2.COLOR_BGR2GRAY)
char_bw = cv2.adaptiveThreshold(char_gray, 255, 
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 9)

(rows, cols) = char_gray.shape

bit_not = cv2.bitwise_not(char_bw)
proj_h = cv2.reduce(bit_nv2.REDUCE_AVG)

proj_v = cv2.reduce(bit_not, 0, cv2.REDUCE_AVG)

thresh_h = 200
thresh_v = 100

start_x, start_y, end_x, end_y = 0, 0, cols - 1, rows - 1
#proj_h = proj_h[0]
proj_v = proj_v[0]

num_iter_h = cols // 8
num_iter_v = rows // 8

for _ in range(num_iter_h):
    if proj_h[start_y][0] > 35:
        start_y += 1

for _ in range(num_iter_h):
    if proj_h[end_y][0] > 160:
        end_y -= 1

for _ in range(num_iter_v):
    if proj_v[start_x] > 15: #25:
        start_x += 1

for _ in range(num_iter_v):
    if proj_v[end_x] > 125:
        end_x -= 1

print('processing.. %s.png' % idx)
output_char = char[start_y:end_y, start_x:end_x]
output_char = get_cropped_char(output_char)
return output_char


def get_cropped_char(img):
    """
    Returns Grayscale cropped image
    """

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blur = cv2.GaussianBlur(img, (3,3), 0)

thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 75, 10)
im2, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

contour = None
for c in cnts:
    area = cv2.contourArea(c)
    if area > 100:
        contour = c
if contour is None: return None
(x, y, w, h) = cv2.boundingRect(contour)
img = img[y:y+h, x:x+w]
return img

我认为在图像阈值后直接裁剪字符不是一个好方法。我相信 morphy-op 可以制造场景。

块元素排列整齐,所以尝试morphy-erode-op分离块(或去除块边界)。获得 clean 字符图像后,您可以轻松裁剪字符图像。

...

英语不好,哈哈哈


这是我得到的结果。

裁剪过的图片。

步骤:

我是 OpenCV 的新手(我正在从事类似的项目...),但这是我根据经验可以说的。提取干净的字符是可能的,至少对于最后两个。由于横跨数字的线,第一个有点困难。

你必须制作图像的灰色版本、阈值并尝试一些 opening/closing operations. After that you have to do 来删除每个方块的 horizontal/vertical 行。 我尝试了我的程序版本,它完成了 40% 的工作。我需要改进它...

之后,根据结果,您必须提取每个数字的边界框。这并不难。有些数字会失败,但大多数会被提取。 "Extremely clean" 很难达到这个水平。

做更多的研究。有很多关于如何执行大多数操作的示例..

编辑:你的图片一定和我的相似。做这样的事情更容易..

这就是我从我身上获得的成果:看看内部方块,每个方块都围绕着一个数字。它们可以很容易地提取并保存以供下一步处理。