使用Python图像库将一张图像切割成多张图像

13 投票
6 回答
32380 浏览
提问于 2025-04-16 17:57

我想用PIL把这张图片切成三部分,然后选中间那一部分。请问我该怎么做呢?

http://thedilbertstore.com/images/periodic_content/dilbert/dt110507dhct.jpg

6 个回答

11

我想给Gourneau的解决方案点赞,但我的声望不够。不过,我想把我根据他的回答写的代码分享出来,可能对其他人有帮助。我还增加了一个功能,可以遍历文件结构,并选择图片的宽度。

import Image
import os

# Set the root directory
rootdir = 'path/to/your/file/directory'

def long_slice(image_path, out_name, outdir, sliceHeight, sliceWidth):
    img = Image.open(image_path) # Load image
    imageWidth, imageHeight = img.size # Get image dimensions
    left = 0 # Set the left-most edge
    upper = 0 # Set the top-most edge
    while (left < imageWidth):
        while (upper < imageHeight):
            # If the bottom and right of the cropping box overruns the image.
            if (upper + sliceHeight > imageHeight and \
                left + sliceWidth > imageWidth):
                bbox = (left, upper, imageWidth, imageHeight)
            # If the right of the cropping box overruns the image
            elif (left + sliceWidth > imageWidth):
                bbox = (left, upper, imageWidth, upper + sliceHeight)
            # If the bottom of the cropping box overruns the image
            elif (upper + sliceHeight > imageHeight):
                bbox = (left, upper, left + sliceWidth, imageHeight)
            # If the entire cropping box is inside the image,
            # proceed normally.
            else:
                bbox = (left, upper, left + sliceWidth, upper + sliceHeight)
            working_slice = img.crop(bbox) # Crop image based on created bounds
            # Save your new cropped image.
            working_slice.save(os.path.join(outdir, 'slice_' + out_name + \
                '_' + str(upper) + '_' + str(left) + '.jpg'))
            upper += sliceHeight # Increment the horizontal position
        left += sliceWidth # Increment the vertical position
        upper = 0

if __name__ == '__main__':
    # Iterate through all the files in a set of directories.
    for subdir, dirs, files in os.walk(rootdir):
        for file in files:
            long_slice(subdir + '/' + file, 'longcat', subdir, 128, 128)
31

假设你有一张非常长的图片,如下所示。

图片

现在你想把它切成更小的竖条,因为它实在太长了。

这里有一个Python脚本可以帮你做到这一点。这对我在准备很长的图片用于LaTeX文档时很有用。

from __future__ import division
import Image
import math
import os

def long_slice(image_path, out_name, outdir, slice_size):
    """slice an image into parts slice_size tall"""
    img = Image.open(image_path)
    width, height = img.size
    upper = 0
    left = 0
    slices = int(math.ceil(height/slice_size))

    count = 1
    for slice in range(slices):
        #if we are at the end, set the lower bound to be the bottom of the image
        if count == slices:
            lower = height
        else:
            lower = int(count * slice_size)  
        #set the bounding box! The important bit     
        bbox = (left, upper, width, lower)
        working_slice = img.crop(bbox)
        upper += slice_size
        #save the slice
        working_slice.save(os.path.join(outdir, "slice_" + out_name + "_" + str(count)+".png"))
        count +=1

if __name__ == '__main__':
    #slice_size is the max height of the slices in pixels
    long_slice("longcat.jpg","longcat", os.getcwd(), 300)

这是切割后的结果

图片


图片


图片

4

如果事先不知道盒子的位置,我会在图像上运行一个简单的边缘检测滤镜,来找出盒子的边界(在x和y方向上都要处理)。

一个简单的方法是:

  1. 对图像运行一个水平边缘滤镜。这样你就得到了一个新图像,每个像素表示它左右两边亮度的变化。也就是说,它会“找到”垂直的线条。
  2. 对于这个水平边缘图像中的每一列,计算它的行的平均绝对值。这样你会得到一个1行宽度的数组,里面的值表示垂直线条的位置,值越高的位置就是线条所在的地方。因为线条可能宽于一个像素,所以在这里你可能需要动点脑筋。
  3. 对另一个方向做同样的处理,以找到水平线条。

如果你认为盒子的边框总是黑色的,可以先提取出黑色(或接近黑色)的像素,作为预处理。但我觉得这可能不是必要的,因为上面的方法应该已经很稳定了。

撰写回答