【问题标题】:How to extract subimages from an image?如何从图像中提取子图像?
【发布时间】:2021-06-12 15:32:51
【问题描述】:

给定主图像,计算和提取所有子图像的方法是什么?

样本 1

输入:

输出应该是 8 个子图。

样本 2

输入:

输出应该有 6 个子图。

注意:这些图片样本取自互联网。图片可以是随机尺寸。

有没有办法在这些图像中画出分隔线,然后根据这些细节进行分割?

例如:

【问题讨论】:

    标签: python opencv machine-learning image-processing computer-vision


    【解决方案1】:

    我不认为,会有一个通用的解决方案可以从任意图表中正确提取所有单个图表(如两个示例所示)——至少使用某种“简单”的图像处理技术。

    对于具有恒定网格布局和单个图形之间恒定颜色空间的“完美”表格(如两个示例所示),以下方法可能是一个想法:

    1. 使用一些自定义参数计算xy 方向的平均标准偏差和阈值。恒定颜色空间内的平均标准偏差应接近于零。这里需要一个自定义参数,因为会有工件,例如来自 JPG 压缩,这种影响可能或多或少严重。
    2. 使用自定义参数对平均标准偏差进行一些二进制关闭。标题或类似内容周围可能有小的恒定颜色空间,参见。第二个例子。同样,这里也需要自定义参数。
    3. 从生成的二进制“信号”中,我们可以提取每个子图像的开始和停止位置,从而通过从原始图像切片来提取子图像本身。注意:仅当表格显示恒定的网格布局时才有效!

    这将是所描述方法的一些代码:

    import cv2
    import numpy as np
    from skimage.morphology import binary_closing
    
    
    def extract_from_table(image, std_thr, kernel_x, kernel_y):
    
        # Threshold on mean standard deviation in x and y direction
        std_x = np.mean(np.std(image, axis=1), axis=1) > std_thr
        std_y = np.mean(np.std(image, axis=0), axis=1) > std_thr
    
        # Binary closing to close small whitespaces, e.g. around captions
        std_xx = binary_closing(std_x, np.ones(kernel_x))
        std_yy = binary_closing(std_y, np.ones(kernel_y))
    
        # Find start and stop positions of each subimage
        start_y = np.where(np.diff(np.int8(std_xx)) == 1)[0]
        stop_y = np.where(np.diff(np.int8(std_xx)) == -1)[0]
        start_x = np.where(np.diff(np.int8(std_yy)) == 1)[0]
        stop_x = np.where(np.diff(np.int8(std_yy)) == -1)[0]
    
        # Extract subimages
        return [image[y1:y2, x1:x2, :]
                for y1, y2 in zip(start_y, stop_y)
                for x1, x2 in zip(start_x, stop_x)]
    
    
    for file in (['image1.jpg', 'image2.png']):
        img = cv2.imread(file)
        cv2.imshow('image', img)
        subimages = extract_from_table(img, 5, 21, 11)
        print('{} subimages found.'.format(len(subimages)))
        for i in subimages:
            cv2.imshow('subimage', i)
            cv2.waitKey(0)
    

    print 输出为:

    8 subimages found.
    6 subimages found.
    

    此外,每个子图像都出于可视化目的而显示。

    对于两个图像,相同的参数是合适的,但这只是巧合!

    ----------------------------------------
    System information
    ----------------------------------------
    Platform:      Windows-10-10.0.16299-SP0
    Python:        3.9.1
    NumPy:         1.20.1
    OpenCV:        4.5.1
    scikit-image:  0.18.1
    ----------------------------------------
    

    【讨论】:

      【解决方案2】:

      我只能使用简单的数组切片技术来提取子图像。我不确定这是否是您正在寻找的。但是如果知道表格的列和行,我想你可以提取子图像。

      image = cv2.imread('table.jpg')
      p = 2 #number of rows
      q = 4 #number of columns
      
      width, height, channels = image.shape
      
      width_patch = width//p
      height_patch = height//q
      x=0
      for i in range(0, width - width_patch, width_patch):
          for j in range(0, height - height_patch, height_patch):
              crop = image[i:i+width_patch, j:j+height_patch]
              cv2.imwrite("image_{0}.jpg".format(x),crop)
              x+=1
              # cv2.imshow('crop', crop)
              # cv2.waitKey(0)```
      

      【讨论】:

        猜你喜欢
        • 2012-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-26
        • 1970-01-01
        • 1970-01-01
        • 2017-04-30
        • 1970-01-01
        相关资源
        最近更新 更多