【问题标题】:Removing grid from an image从图像中删除网格
【发布时间】:2018-07-07 13:20:15
【问题描述】:

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

示例照片:

(1) 原始 RGB 照片

(2) 模糊灰度

(3) 应用自适应阈值后

注意: 我希望我的算法能够处理任何颜色的表格网格。

任何代码 sn-ps 将不胜感激。 提前致谢。

【问题讨论】:

    标签: python opencv image-processing scikit-image


    【解决方案1】:

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

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

    【讨论】:

    • 您能否将链接资源的相关部分包含在您的答案中?照原样,您的答案很容易受到链接失效的影响(即,如果链接的资源更改或消失,您的答案就没有帮助)。
    • 我唯一的问题是分数栏也会被删除(在提取水平线时)。
    • 有没有办法保存分数条?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      Result

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

      我看到了解决这个问题的两种方法:

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

      2. 简单的方法:应用一般的图像处理,除了假设笔总是比网格更暗,并且输出是二进制(黑笔/白页)之外,对问题知之甚少。

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

      我们首先注意到页面的“白色”实际上是一种不均匀的灰色阴影(如果我们转换为灰度)。 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])
      

      【讨论】:

        猜你喜欢
        • 2017-06-08
        • 1970-01-01
        • 2014-07-06
        • 1970-01-01
        • 2020-12-25
        • 2015-04-17
        • 2019-04-01
        • 1970-01-01
        相关资源
        最近更新 更多