from PIL import Image
def subdivide(file, nx, ny):
im = Image.open(file)
wid, hgt = im.size # Size of input image
w = int(wid/nx) # Width of each subimage
h = int(hgt/ny) # Height of each subimage
for i in range(nx):
x1 = i*w # Horicontal extent...
x2 = x1+w # of subimate
for j in range(ny):
y1 = j*h # Certical extent...
y2 = y1+h # of subimate
subim = im.crop((x1, y1, x2, y2))
subim.save(f'{i}x{j}.png')
subdivide("cat.png", 2, 2)
from PIL import Image
import numpy as np
def slices(lst):
""" Finds the indices where lst changes value and returns them in pairs
lst is a list of booleans
"""
edges = [lst[i-1] ^ lst[i] for i in range(len(lst))]
indices = [i for i,v in enumerate(edges) if v]
pairs = [(indices[i], indices[i+1]) for i in range(0, len(indices), 2)]
return pairs
def extract(xx_locs, yy_locs, image, prefix="image"):
""" Locate and save the subimages """
data = np.asarray(image)
for i in range(len(xx_locs)):
x1,x2 = xx_locs[i]
for j in range(len(yy_locs)):
y1,y2 = yy_locs[j]
arr = data[y1:y2, x1:x2, :]
Image.fromarray(arr).save(f'{prefix}-{i}-{j}.png')
def assemble(xx_locs, yy_locs, prefix="image", result='composite'):
""" Paste the subimages into a single image and save """
wid = sum([p[1]-p[0] for p in xx_locs])
hgt = sum([p[1]-p[0] for p in yy_locs])
dst = Image.new('RGB', (wid, hgt))
x = y = 0
for i in range(len(xx_locs)):
for j in range(len(yy_locs)):
img = Image.open(f'{prefix}-{i}-{j}.png')
dst.paste(img, (x,y))
y += img.height
x += img.width
y = 0
dst.save(f'{result}.png')
WHITE_THRESH = 110 # The original image borders are not actually white
image_file = 'cat.png'
image = Image.open(image_file)
# To detect the (almost) white borders, we make a grayscale version of the image
gray = np.asarray(image.convert('L'))
# Detect location of images along the x axis
whitespace = [np.all(gray[:,i] > WHITE_THRESH) for i in range(gray.shape[1])]
xx_locs = slices(whitespace)
# Detect location of images along the y axis
whitespace = [np.all(gray[i,:] > WHITE_THRESH) for i in range(gray.shape[0])]
yy_locs = slices(whitespace)
extract(xx_locs, yy_locs, image, prefix='fragment')
assemble(xx_locs, yy_locs, prefix='fragment', result='composite')
2条答案
按热度按时间ajsxfq5m1#
下面是一个解决方案,适用于我们知道网格配置的“简单”情况。我提供了这个解决方案,尽管我怀疑这是要求您做的事情。
在猫的示例图像中,如果给定网格配置2x2,我们可以:
以上操作将创建这些图像:
tpgth1q72#
我之前的答案依赖于知道输入图像的网格配置,而这个解决方案不知道。
主要的挑战是检测边界在哪里,因此,包含图像的矩形位于哪里。
为了检测边界,我们将寻找(垂直和水平)所有像素都是“白色”的图像线。由于图像中的边界并不是真正的纯白,我们将使用一个小于255的值作为白度阈值(代码中的WHITE_THRESH)。
算法的要点在以下代码行中:
这里的“whitespace”是一个布尔值列表,看起来像
其中“T”表示相应的水平位置是边界的一部分(白色)。
我们感兴趣的是T和F之间存在转换的x位置。对函数***slices(whitespace)***的调用返回索引元组的列表
其中每个(x1,x2)对指示图像在x轴方向上的xmin和xmax位置。
slices函数使用异或运算符找到在True和False之间存在转换的“边”,然后以元组列表(索引对)的形式返回转换的位置。
类似的代码用于检测边界和图像的垂直位置。
以下完整的可运行代码将OP的图像“cat.png”作为输入,并且:
1.将子图像提取到4个PNG文件“片段-0-0.png”、“片段-0-1.png”、“片段-1-0.png”和“片段-1-1.png”中。
1.通过将上述片段粘贴在一起创建原始图像的(无边框)版本。
接下来是可运行的代码和生成的图像。程序运行大约0. 25秒。
单个片段:
合成图像: