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. How do I do it?
http://thedilbertstore.com/images/pe开发者_如何学JAVAriodic_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. This was useful to me for in preparing very long images for LaTeX docs.
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')
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.
A simple approach would be:
- 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. I.e. it will "find" vertical lines.
- 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. Since the lines are more than one pixel wide yo might have to be a bit clever here.
- 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.
Look at the crop() method of PIL
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).
- Load the Image
- Get the Size
- Use the Crop method
- Save the middle image
精彩评论