Разрезание одного изображения на несколько изображений с помощью библиотеки изображений Python - PullRequest
13 голосов
/ 19 мая 2011

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

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

Ответы [ 6 ]

28 голосов
/ 10 января 2013

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

Picture

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

Вот скрипт 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)

Это вывод

Picture


Picture


Picture

9 голосов
/ 09 апреля 2014

Я хотел проголосовать за решение Гурно , но ему не хватает репутации.Однако я решил опубликовать код, который я разработал в результате его ответа, на случай, если он будет полезен кому-то еще.Я также добавил возможность перебирать файловую структуру и выбирать ширину изображения.

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)
7 голосов
/ 19 мая 2011

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

import Image
i = Image.open('dt110507dhct.jpg')
frame2 = i.crop(((275, 0, 528, 250)))
frame2.save('dt110507dhct_frame2.jpg')
3 голосов
/ 19 мая 2011

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

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

  1. Запустить горизонтальный фильтр по краям изображения. Теперь у вас есть изображение, где каждый пиксель описывает изменения интенсивности слева и справа от этого пикселя. То есть он "найдет" вертикальные линии.
  2. Для каждого столбца в изображении горизонтального края получите среднюю абсолютную величину его рядов. В полученном массиве размером 1 x WIDTH вы найдете вертикальные линии в позициях с наибольшим значением. Так как строки имеют ширину более одного пикселя, возможно, вам придется быть немного умнее.
  3. Сделайте то же самое для другой оси, чтобы найти горизонтальные линии.

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

3 голосов
/ 19 мая 2011

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

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

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

0 голосов
/ 19 мая 2011
  1. Загрузить изображение
  2. Получить размер
  3. Используйте метод Crop
  4. Сохранить среднее изображение
...