Вопрос по python, image, image-processing – Добавление границ к изображению с помощью Python

24

У меня есть большое количество изображений фиксированного размера (скажем, 500 * 500). Я хочу написать скрипт на Python, который изменит их размер до фиксированного размера (скажем, 800 * 800), но сохранит исходное изображение в центре и заполнит лишнюю область фиксированным цветом (скажем, черным).

Я использую PIL. Я могу изменить размер изображения, используяresize функция сейчас, но это меняет соотношение сторон. Есть какой-либо способ сделать это?

Ваш Ответ

6   ответов
38

Вы можете создать новое изображение с желаемым новым размером и вставить старое изображение в центр, а затем сохранить его. Если вы хотите, вы можете перезаписать исходное изображение (вы уверены?; O)

import Image

old_im = Image.open('someimage.jpg')
old_size = old_im.size

new_size = (800, 800)
new_im = Image.new("RGB", new_size)   ## luckily, this is already black!
new_im.paste(old_im, ((new_size[0]-old_size[0])/2,
                      (new_size[1]-old_size[1])/2))

new_im.show()
# new_im.save('someimage.jpg')
2

Вы можете загрузить изображение сscipy.misc.imread в виде массива. Затем создайте массив с нужным фоном сnumpy.zeros((height, width, channels)) и вставьте изображение в нужное место:

import numpy as np
import scipy.misc

im = scipy.misc.imread('foo.jpg', mode='RGB')
height, width, channels = im.shape

# make canvas
im_bg = np.zeros((height, width, channels))
im_bg = (im_bg + 1) * 255  # e.g., make it white

# Your work: Compute where it should be
pad_left = ...
pad_top = ...

im_bg[pad_top:pad_top + height,
      pad_left:pad_left + width,
      :] = im
# im_bg is now the image with the background.
28

Да, есть.

Сделайте что-то вроде этого:

import Image, ImageOps
ImageOps.expand(Image.open('original-image.png'),border=300,fill='black').save('imaged-with-border.png')

Вы можете написать то же самое в несколько строк:

import Image, ImageOps
img = Image.open('original-image.png')
img_with_border = ImageOps.expand(img,border=300,fill='black')
img_with_border.save('imaged-with-border.png')

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

import Image, ImageOps
for i in list-of-images:
  img = Image.open(i)
  img_with_border = ImageOps.expand(img,border=300,fill='black')
  img_with_border.save('bordered-%s' % i)
хорошо нашел работу,ImageOps.expand(Image.open('original-image.png'),border=(300,500),fill='black').save('imaged-with-border.png') Nihar Sarangi
Интересно. Можно ли было выбрать разные границы для верха-низа и слева-справа, чтобы параметром вместо размера границы мог быть новый размер изображения?
ImageOps.expand, похоже, работает в большинстве ситуаций, хотя он создает проблемы с большими изображениями (5500x5500 пикселей). По какой-то причине изображения получаются в оттенках серого, в то время как точно такой же код, работающий на небольших изображениях, работает отлично. Учитывая это, я разместил ответ ниже об использовании Image.crop, который, похоже, не имеет такого же ограничения / ошибки.
Спасибо, я могу сделать значения x и y границы разными ... что-то вроде сказать (100,50)? Nihar Sarangi
9

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

import cv2

img = cv2.imread('image.jpg')

color = [101, 52, 152] # 'cause purple!

# border widths; I set them all to 150
top, bottom, left, right = [150]*4

img_with_border = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)

Example results of cv2.copyMakeBorder function

Источники:OpenCV границы учебника а также Документы OpenCV 3.1.0 для copyMakeBorder

Чтобы воспроизвести последнее изображение, на котором реплицируются пиксели на границе изображения, вы можете просто использоватьcv2.BORDER_REPLICATE как тип границы, и вам не нужно указывать значение цвета, например:img_with_border = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REPLICATE)
Я думаю, что вы должны добавитьcv2.BORDER_CONSTANT перед определениемvalue=color как вdocs.opencv.org/3.1.0/d3/df2/tutorial_py_basic_ops.html
2

Здесь важно учитывать старое измерение, новое измерение и их различие. Если разница нечетная (не четная), вам нужно будет указать слегка отличающиеся значения дляleft, top, right а такжеbottom границы.

Предположим, что старое измерение - это о, а новое - это nw, nh. Итак, это будет ответ:

import Image, ImageOps
img = Image.open('original-image.png')
deltaw=nw-ow
deltah=nh-oh
ltrb_border=(deltaw/2,deltah/2,deltaw-(deltaw/2),deltah-(deltah/2))
img_with_border = ImageOps.expand(img,border=ltrb_border,fill='black')
img_with_border.save('imaged-with-border.png')
2

PIL & APOS; scrop метод может фактически обработать это для вас, используя числа, которые находятся за пределами ограничительной рамки исходного изображения, хотя это явно не указано вдокументация, Отрицательные числа для левого и верхнего добавят черные пиксели к этим краям, а числа, превышающие исходную ширину и высоту для правого и нижнего, добавят черные пиксели к этим краям.

Этот код учитывает нечетные размеры пикселей:

from PIL import Image

with Image.open('/path/to/image.gif') as im:
    old_size = im.size
    new_size = (800, 800)

    if new_size > old_size:
        # Set number of pixels to expand to the left, top, right,
        # and bottom, making sure to account for even or odd numbers
        if old_size[0] % 2 == 0:
            add_left = add_right = (new_size[0] - old_size[0]) // 2
        else:
            add_left = (new_siz,e[0] - old_size[0]) // 2
            add_right = ((new_size[0] - old_size[0]) // 2) + 1

        if old_size[1] % 2 == 0:
            add_top = add_bottom = (new_size[1] - old_size[1]) // 2
        else:
            add_top = (new_size[1] - old_size[1]) // 2
            add_bottom = ((new_size[1] - old_size[1]) // 2) + 1

        left = 0 - add_left
        top = 0 - add_top
        right = old_size[0] + add_right
        bottom = old_size[1] + add_bottom

        # By default, the added pixels are black
        im = im.crop((left, top, right, bottom))

Вместо 4-х кортежей вы можете использовать 2-кортеж, чтобы добавить одинаковое количество пикселей слева / справа и сверху / снизу, или 1-кортеж, чтобы добавить одинаковое количество пикселей со всех сторон.

Похожие вопросы