【发布时间】:2021-06-12 15:32:51
【问题描述】:
给定主图像,计算和提取所有子图像的方法是什么?
样本 1
输入:
输出应该是 8 个子图。
样本 2
输入:
输出应该有 6 个子图。
注意:这些图片样本取自互联网。图片可以是随机尺寸。
有没有办法在这些图像中画出分隔线,然后根据这些细节进行分割?
例如:
【问题讨论】:
标签: python opencv machine-learning image-processing computer-vision
给定主图像,计算和提取所有子图像的方法是什么?
输入:
输出应该是 8 个子图。
输入:
输出应该有 6 个子图。
注意:这些图片样本取自互联网。图片可以是随机尺寸。
有没有办法在这些图像中画出分隔线,然后根据这些细节进行分割?
例如:
【问题讨论】:
标签: python opencv machine-learning image-processing computer-vision
我不认为,会有一个通用的解决方案可以从任意图表中正确提取所有单个图表(如两个示例所示)——至少使用某种“简单”的图像处理技术。
对于具有恒定网格布局和单个图形之间恒定颜色空间的“完美”表格(如两个示例所示),以下方法可能是一个想法:
x 和y 方向的平均标准偏差和阈值。恒定颜色空间内的平均标准偏差应接近于零。这里需要一个自定义参数,因为会有工件,例如来自 JPG 压缩,这种影响可能或多或少严重。这将是所描述方法的一些代码:
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
----------------------------------------
【讨论】:
我只能使用简单的数组切片技术来提取子图像。我不确定这是否是您正在寻找的。但是如果知道表格的列和行,我想你可以提取子图像。
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)```
【讨论】: