Резка одного изображения на несколько изображений с помощью библиотеки изображений Python

Мне нужно разрезать это изображение на три части с помощью PIL и выбрать среднюю часть. Как мне это сделать?

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

6 ответов


Если коробки не известны раньше, я бы запустил простой фильтр поиска ребер над изображением (как X, так и y), чтобы найти границы коробки.

простой подход был бы:

  1. запустить горизонтальный фильтр края над изображением. Теперь у вас есть изображение, где каждый пиксель описывает изменения интенсивности слева и справа от этого пикселя. Т. е. он будет" находить " вертикальные линии.
  2. для каждого столбца в горизонтальном-edge-image получить среднее абсолютное величина его строк. В результирующем массиве размером 1 X WIDTH вы найдете вертикальные линии в позициях наибольшего значения. Поскольку линии имеют ширину более одного пикселя, возможно, здесь нужно быть немного умным.
  3. сделать то же самое для другой оси, чтобы найти горизонтальные линии.

вы можете выполнить предварительную обработку, сначала извлекая только черные пиксели (или почти черные), Если вы считаете, что границы ящиков всегда будут черный. Но я сомневаюсь, что это будет необходимо, так как вышеуказанный метод должен быть очень стабильным.


скажем, у вас есть очень длинная картина такая.

Picture

и теперь вы хотите разрезать его на меньшие вертикальные биты, потому что он такой длинный.

вот скрипт Python, который это сделает. Это было полезно для меня при подготовке очень длинных изображений для 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)

это вывод

Picture


Picture


Picture


Я хотел проголосовать 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)

для этого конкретного изображения вы могли бы сделать

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

посмотрите на метод crop () PIL

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

(требуется знание ограничивающей рамки изображения...предполагая, что изображение имеет одинаковые размеры каждый день, Вы должны иметь возможность определить ограничивающую рамку один раз и использовать ее все время).


  1. загрузить изображения
  2. получить размер
  3. использовать метод
  4. Сохранить Изображение посередине