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

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

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

Ответ 1

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

Простым подходом будет:

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

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

Ответ 2

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

Picture

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

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

Ответ 3

Я хотел поднять решение в 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)

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

  • Загрузите изображение
  • Получить размер
  • Используйте метод Crop
  • Сохранить среднее изображение