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

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

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


person un33k    schedule 19.05.2011    source источник


Ответы (6)


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

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

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

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

person Hannes Ovrén    schedule 19.05.2011
comment
Мне нужно автоматизировать это, иногда линии нарисованы от руки, но линии точно есть. Ваш ответ великолепен, но мне интересно, есть ли у вас фрагмент кода для размещения здесь? или ссылку на сайт где это делается? Размер каждого поля (подизображения) может быть не фиксированным, поэтому автоматическое определение полей - это то, что я ищу? Я хочу дать изображение любого размера с коробками в нем и получить отдельные изображения. Таким образом, алгоритм должен делать наилучшие предположения при нахождении вертикальных и горизонтальных линий. Спасибо за кучу. - person un33k; 21.05.2011
comment
Извините, у меня нет кода. Но похоже, что в PIL есть то, что нужно: я предполагаю, что фильтр FIND_EDGES на этой странице pythonware.com/library/pil/handbook/imagefilter.htm будет полезен. К сожалению, похоже, что это могло бы получить ребра для X и Y одновременно. Но вы можете определить свое собственное ядро ​​фильтра. Для горизонтального попробуйте [-1, 0, 1] и для вертикального, то же самое, но как вектор-столбец вместо вектора-строки. - person Hannes Ovrén; 23.05.2011

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

Изображение

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

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

Это выход

Изображение


Изображение


Изображение

person Gourneau    schedule 10.01.2013

Я хотел проголосовать за решение 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)
person BBQ Singular    schedule 09.04.2014

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

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

Посмотрите на метод урожая () PIL

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

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

person Andreas Jung    schedule 19.05.2011

  1. Загрузите изображение
  2. Получить размер
  3. Используйте метод Crop.
  4. Сохраните среднее изображение
person Andrew    schedule 19.05.2011