简体   繁体   English

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

[英]Cutting one image into multiple images using the Python Image Library

I need to cut this image into three parts using PIL and pick the middle part. 我需要使用PIL将此图像分为三部分,然后选择中间部分。 How do I do it? 我该怎么做?

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

Say you have a really long picture like this. 假设您的图片非常长。

图片

And now you want to slice it up into smaller vertical bits, because it is so long. 现在,您想将其切成较小的垂直位,因为它很长。

Here is a Python script that will do that. 这是一个将执行此操作的Python脚本。 This was useful to me for in preparing very long images for LaTeX docs. 这对我为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)

This is is the output 这是输出

图片


图片


图片

I wanted to up-vote Gourneau's solution, but lack the sufficient reputation. 我想投票支持古尔诺的解决方案,但缺乏足够的声誉。 However, I figured I would post the code that I developed as a result of his answer just in case it might be helpful to somebody else. 但是,我认为我会发布我根据他的回答开发的代码,以防万一它可能对其他人有所帮助。 I also added the ability to iterate through a file structure, and choose an image width. 我还添加了遍历文件结构并选择图像宽度的功能。

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)

For this particular image you would do 对于这个特定的图像,你会做

import Image
i = Image.open('dt110507dhct.jpg')
frame2 = i.crop(((275, 0, 528, 250)))
frame2.save('dt110507dhct_frame2.jpg')

Look at the crop() method of PIL 看一下PIL的crop()方法

http://effbot.org/imagingbook/image.htm http://effbot.org/imagingbook/image.htm

(requires knowledge of the bounding box of the image...assuming that the image has the same dimensions every day you should be able to determine the bounding box once and use it for all the time). (需要了解图像的边界框...假设图像每天都有相同的尺寸,那么您应该能够一次确定边界框并一直使用它)。

If the boxes are not known on before hand I would run a simple edge finding filter over the image (both x and y directions) to find the boundaries of the box. 如果事先不知道盒子,我将对图像(x和y方向)运行一个简单的边缘查找过滤器,以找到盒子的边界。

A simple approach would be: 一种简单的方法是:

  1. Run horizontal edge filter over image. 对图像运行水平边缘滤镜。 You now have an image where each pixel describes the changes in intensity left and right of that pixel. 现在,您有一个图像,其中每个像素描述该像素左右强度的变化。 Ie it will "find" vertical lines. 即它将“找到”垂直线。
  2. For each column in the horizontal-edge-image get the average absolute magnitude of its rows. 对于水平边缘图像中的每一列,获取其行的平均绝对大小。 In the resulting 1 x WIDTH sized array you will find the vertical lines at the positions of highest value. 在生成的1 x WIDTH大小的数组中,您将在最高值的位置找到垂直线。 Since the lines are more than one pixel wide yo might have to be a bit clever here. 由于线条超过一个像素宽,因此您在这里可能会有点聪明。
  3. Do the same for the other axis to find the horizontal lines. 对另一个轴执行相同操作,以找到水平线。

You could do some pre processing by first extracting only pixels that are black (or near black) if you believe that the borders of the boxes will always be black. 如果您认为框的边界始终是黑色的,则可以先仅提取黑色(或接近黑色)的像素来进行一些预处理。 But I doubt it'd be necessary since the above method should be very stable. 但是我怀疑是否有必要,因为上述方法应该非常稳定。

  1. Load the Image 加载图像
  2. Get the Size 取得尺寸
  3. Use the Crop method 使用裁切方法
  4. Save the middle image 保存中间图像

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM