从图像中删除网格

时间:2018-01-28 20:58:00

标签: python opencv image-processing scikit-image

我正在开发一个项目,让用户可以拍摄手写公式的照片并将其发送到我的服务器。我想只留下与数学相关的符号,而不是表格。

样本照片:

(1)原始RGB照片 Original photo (RGB

(2)模糊灰度 Blurred grayscale photo

(3)应用自适应阈值后 After applying Adaptive Threshold

注意: 我希望我的算法可以处理任何颜色的图纸网格。

任何代码段都将不胜感激。 提前谢谢。

3 个答案:

答案 0 :(得分:3)

Result

这是一个具有挑战性的问题,在不确切知道预期的纸张/线条和墨水组合类型以及输出将用于什么样的情况下进行概括。我以为我会尝试它并且可能会学到一些东西。

我认为有两种方法可以解决这个问题:

  1. 聪明的方法:识别网格,颜色,方向,大小以找到它所占据的图像区域,以便忽略它。这里有一些重要的警告需要解决。例如页面可能不会被拍到平面和平方(经线,扭曲,旋转都要占)。还有一些我们不想删除的行。

  2. 简单的方法:应用一般的图像处理,除了笔总是比网格更暗的假设之外几乎不了解问题,输出是二进制(黑色笔/白页)。 / p>

  3. 我更喜欢第二个,因为它更容易实现和更好地概括。

    我们首先注意到页面的“白色”实际上是不均匀的灰色阴影(如果我们转换为灰度)。 CV自适应阈值处理很好地解决了这个问题。它几乎让我们在那里。

    下面的代码处理50x50像素块中的图像,以解决照明的不均匀性。在每个块中,我们在应用阈值之前减去中值。一个简单的解决方案,但也许你需要的。我没有在许多图像上测试它,阈值和预处理和后处理可能需要调整。如果输入图像变化很大,或者网格相对于墨水太暗,则无效。

    import cv2
    import numpy
    import sys
    
    BLOCK_SIZE = 50
    THRESHOLD = 25
    
    
    def preprocess(image):
        image = cv2.medianBlur(image, 3)
        image = cv2.GaussianBlur(image, (3, 3), 0)
        return 255 - image
    
    
    def postprocess(image):
        image = cv2.medianBlur(image, 5)
        # image = cv2.medianBlur(image, 5)
        # kernel = numpy.ones((3,3), numpy.uint8)
        # image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
        return image
    
    
    def get_block_index(image_shape, yx, block_size): 
        y = numpy.arange(max(0, yx[0]-block_size), min(image_shape[0], yx[0]+block_size))
        x = numpy.arange(max(0, yx[1]-block_size), min(image_shape[1], yx[1]+block_size))
        return numpy.meshgrid(y, x)
    
    
    def adaptive_median_threshold(img_in):
        med = numpy.median(img_in)
        img_out = numpy.zeros_like(img_in)
        img_out[img_in - med < THRESHOLD] = 255
        return img_out
    
    
    def block_image_process(image, block_size):
        out_image = numpy.zeros_like(image)
        for row in range(0, image.shape[0], block_size):
            for col in range(0, image.shape[1], block_size):
                idx = (row, col)
                block_idx = get_block_index(image.shape, idx, block_size)
                out_image[block_idx] = adaptive_median_threshold(image[block_idx])
    
        return out_image
    
    
    def process_image_file(filename):
        image_in = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2GRAY)
    
        image_in = preprocess(image_in)
        image_out = block_image_process(image_in, BLOCK_SIZE)
        image_out = postprocess(image_out)
    
        cv2.imwrite('bin_' + filename, image_out)
    
    
    if __name__ == "__main__":
        process_image_file(sys.argv[1])
    

答案 1 :(得分:0)

OpenCV有一个关于从图像中删除网格的教程:

“使用形态学操作提取水平和垂直线”,OpenCV文档, 来源:https://docs.opencv.org/master/dd/dd7/tutorial_morph_lines_detection.html

答案 2 :(得分:0)

这是一项非常艰巨的任务。我也有这个问题,我发现解决方案不能100%准确。顺便说一句,就在几天前,我看到this link。也许它会有所帮助。