Пропорциональное изменение размера изображения python

OpenCV — быстрый старт: базовые операции с изображениями

Судя по количеству закладок на первой части, работа моя — не зряшная.
В прошлый раз разбирали скучное открывание-закрывание картинки, в этот раз засунем в неё руки поглубже:

  • Доступ к пикселям и работа с ними.
  • Масштабирование картинки.
  • Обрезка.
  • Отражение.
import cv2 import numpy as np import matplotlib.pyplot as plt from PIL import Image

Первой картинкой пойдут уже знакомые шашечки:

Доступ к отдельным пикселям

Изображение в OpenCV — матрица numpy, а значит, для доступа к пикселю будем использовать нотацию матриц: [ r , c ]. Первое значение — строка, второе — колонка. Не забывайте о том, что индексация начинается с нуля!

Для доступа к самому первому пикселю обратимся к элементу матрицы (изображения, то бишь) с индексами 0 и 0:

# Читаем картинку как чб cb_img = cv2.imread("checkerboard_18x18.png",0) # Выводим массив, представляющий картинку print(cb_img) # Выводим значение самого первого пикселя (верх-лево) print(cb_img[0,0]) # Выводим значение первого пикселя слева от чёрной зоны print(cb_img[0,6])

С доступом разобрались, поиграем со значениями.

Изменение пикселей

Просто переназначаем пиксель:

Читайте также:  Python двумерный массив создание

Что-то похожее мы сделали в прошлый раз с каналами.

Продублируем картинку, и накидаем в неё серых пикселей:

cb_img_copy = cb_img.copy() # копируем загруженное изображение cb_img_copy[2,2] = 200 # пиксель в ячейке [2,2] будет равен 200 cb_img_copy[2,3] = 200 # и так далее cb_img_copy[3,2] = 200 cb_img_copy[3,3] = 200 # То же самое другими словами: # cb_img_copy[2:3,2:3] = 200 plt.imshow(cb_img_copy, cmap='gray') plt.show() print(cb_img_copy)

Обрезка картинок

Можно воспринимать кроп как задачу «из пачки пикселей берём только эти несколько».
Загрузим новозеландскую лодку и потренируемся на ней:

Пропорциональное изменение размера изображения python

img_NZ_bgr = cv2.imread("New_Zealand_Boat.jpg",cv2.IMREAD_COLOR) # или так: # img_NZ_bgr = cv2.imread("New_Zealand_Boat.jpg",1) # img_NZ_bgr = cv2.imread("New_Zealand_Boat.jpg") img_NZ_rgb = img_NZ_bgr[. -1] # или так: # img_NZ_rgb = cv2.cvtColor(img_NZ_bgr, cv2.COLOR_BGR2RGB) # или разбить на каналы и пересобрать в правильном порядке :) plt.imshow(img_NZ_rgb) plt.show()
# кропнутый регион = область загруженной картинки # c 200 по 400 строку (или Y, если хотите) # и 300 по 600 колонку (или X, если хотите) cropped_region = img_NZ_rgb[200:400, 300:600] plt.imshow(cropped_region) plt.show()

Масштабирование изображений

Функция resize() отресайзит картинку в больший или меньший размер. А регулируется это всё аргументами src , dsize (обязательные), fx , fy (факультативные).

cv2.resize() — синтаксис и аргументы

dst = resize( src, dsize[, dst[, fx[, fy[, interpolation]]]] )

dst — изображение на выходе. Размер картинки будет равен dsize (если он ненулевой), или посчитан через src.size() , fx , fy .
Тип данных будет тем же, что и в оригинальной картинке.

src — понятно, сама картинка, требующая вмешательства. Обязательный аргумент.
dsize — необходимый размер, обязательный аргумент.
fx — коэффициент масштаба горизонтальный.
fy — коэффициент масштаба вертикальный.

Чуть подробнее о том, что тут происходит

В общем: в dsize кладётся кортеж с натуральными числами, две штуки: (500, 500). Это размер, в который картинка отмасштабируется.
Можно воспользоваться вместо этого коэффициентами масштаба, тогда вместо dsize надо впечатать None .
Коэффициенты масштаба — fx и fy — берут оригинальную картинку, и растягивают/стягивают её пропорционально.

dsize — имеет приоритет: конструкция resize(src, dsize=(100, 100),fx=20, fy=20) выдаст картинку 100×100 пикселей.

Первый вариант масштабирования: коэффициенты масштаба

Увеличим кропнутую лодку в два раза:

resized_cropped_region_2x = cv2.resize(cropped_region,None,fx=2, fy=2) plt.imshow(resized_cropped_region_2x) plt.show()

Второй вариант масштабирования: сразу укажем нужные размеры

desired_width = 100 # желаемая ширина desired_height = 200 # желаемая высота dim = (desired_width, desired_height) # размер в итоге # Масштабируем картинку resized_cropped_region = cv2.resize(cropped_region, dsize = dim, interpolation = cv2.INTER_AREA) # Или так: # resized_cropped_region = cv2.resize(cropped_region, # dsize = (100, 200), # interpolation = cv2.INTER_AREA) plt.imshow(resized_cropped_region) plt.show()

Масштабирование с сохранением пропорций

За основу возьмём вторую методу, но отталкиваться будем от желаемой ширины.
Немного несложной математики:

# Используем 'dsize' desired_width = 100 # желаемая ширина # соотношение сторон: ширина, делённая на ширину оригинала aspect_ratio = desired_width / cropped_region.shape[1] # желаемая высота: высота, умноженная на соотношение сторон desired_height = int(cropped_region.shape[0] * aspect_ratio) dim = (desired_width, desired_height) # итоговые размеры # Масштабируем картинку resized_cropped_region = cv2.resize(cropped_region, dsize=dim, interpolation=cv2.INTER_AREA) plt.imshow(resized_cropped_region) plt.show()

Сохранимся-с!

# Приводим картинку к RGB resized_cropped_region_2x = resized_cropped_region_2x[. -1] # Сохраняем картинку cv2.imwrite("resized_cropped_region_2x.png", resized_cropped_region_2x) # Посмотрим на сокранённую картинку (тут-то нам и пригодится подгруженный PIL) im = Image.open('resized_cropped_region_2x.png') im.show()

Отражение картинки

Происходит с помощью функции flip() .

src — понятно, сама картинка, требующая вмешательства. Обязательный аргумент.
flipCode — флаг, объясняющий функции, как конкретно мы хотим картинку отразить.

img_NZ_rgb_flipped_horz = cv2.flip(img_NZ_rgb, 1) img_NZ_rgb_flipped_vert = cv2.flip(img_NZ_rgb, 0) img_NZ_rgb_flipped_both = cv2.flip(img_NZ_rgb, -1) plt.figure(figsize=[18,5]) plt.subplot(141);plt.imshow(img_NZ_rgb_flipped_horz);plt.title("Horizontal Flip"); plt.subplot(142);plt.imshow(img_NZ_rgb_flipped_vert);plt.title("Vertical Flip") plt.subplot(143);plt.imshow(img_NZ_rgb_flipped_both);plt.title("Both Flipped") plt.subplot(144);plt.imshow(img_NZ_rgb);plt.title("Original")

Вот и всё! Второй маленький шажок к человеку-фотошопу пройден! До встречи в следующих сериях.

Источник

Меняем размер изображения в Python Pillow с обрезанием и изменением ширины и высоты

Изменение размера картинки в Python с Pillow (PIL) с resize() и crop() и другими методами

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

Pillow не является стандартной библиотекой и устанавливается отдельно:

Получение размеров

Для получения размера картинки мы должны открыть ее (создать объект класса Image) и получить атрибут ‘size’. Это можно сделать так:

from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) # получаем ширину и высоту width, height = img.size print(width, height) # открываем картинку в окне img.show()

Получение ширины и высоты картинки в Python Pillow

Изменение размера изображения с resize()

Для изменения ширины и высоты есть метод ‘resize’. Этот метод не изменяет текущую картинку, а возвращает новую. Новый размер мы должны указать в виде кортежа ‘(ширина, высота)’. Сохранить картинку можно через метод ‘save’:

from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) # изменяем размер new_image = img.resize((200, 385)) new_image.show() # сохранение картинки new_image.save('F:/hello2.png')

Изменение размера картинки в Python Pillow

На примере выше видно, что картинка меняется не пропорционально. Это можно изменить двумя способами:

Учет соотношения сторон

Что бы создать пропорциональную картинку вам нужно определиться с размером одно из сторон. В примере ниже указана фиксированная ширина, но вы можете немного изменить скрипт и указать высоту. Мы должны вычислить процентное соотношение старой ширины к новой, а затем умножить ее на высоту:

from PIL import Image image_path = 'F:/hello.png' # указываем фиксированный размер стороны fixed_width = 200 img = Image.open(image_path) # получаем процентное соотношение # старой и новой ширины width_percent = (fixed_width / float(img.size[0])) # на основе предыдущего значения # вычисляем новую высоту height_size = int((float(img.size[0]) * float(width_percent))) # меняем размер на полученные значения new_image = img.resize((fixed_width, height_size)) new_image.show() new_image.save('F:/hello2.png')

Пропорциональное изменение размера изображения в Python Pillow

Создание эскиза thumbnail

Есть еще один способ выполнить предыдущие шаги автоматически — он называется ‘thumbnail’. Его отличие от resize() в том, что он не может увеличить размер изображения. Если с помощью resize() вы можете изменить размер 200х200 на 400х400, то метод thumbnail() оставит исходный.

В методе ‘thumbnail()’ создается кортеж с 2-мя числами: максимальная ширина и высота. Понятие «максимальный» нужно оценивать как значение, которое можно менять в меньшую сторону. Если вы возьмете картинку размером 100х100 и захотите ее уменьшить до 100х50, то Pillow высчитает оптимальны размер как 50х50.

from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) # пропорциональное изменение картинки img.thumbnail(size=(350,400)) img.show() img.save('F:/hello3.png')

Создание мини-изображение с методом thumbnail в Python Pillow

Обрезание (cropping) картинки

Для обрезания ненужных частей картинки используется метод ‘crop()’. Внутри этого метода помещается кортеж со значениями (отступами) соответствующие сторонам, которые нужно обрезать. Стороны можно определить следующими переменными:

Оси x1 и y1 находятся в левой верхней части изображения, а оси x2 и y2 в правой нижней. Левая верхняя часть имеет координаты 0 и 0, а правая нижняя соответствует ширине и высоте изображения. Картинка, которую я использовал в предыдущих примерах, имеет размер 401х385. Если распределить все координаты, соответствующие этой картинке, получится следующий результат:

Оси при обрезании изображения с crop() в Python Pillow

Представим, что нам нужно обрезать название на картинке — это примерно 60px. Мы должны вычесть (вырезать) это значение из нижнего правого угла (высоты):

from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) size = img.size width, height = img.size # обрезаем картинку new_image = img.crop((0,0,width,height-60)) new_image.show() new_image.save('F:/hello3.png') 

Обрезание изображения с crop() в Python Pyllow

Если бы мы хотели оставить только название, то нужно было бы изменить значение y1 (2-ой индекс):

Обрезание изображения с crop() в Python Pyllow

Создание границ картинки и ее увеличение за счет новой области

Увеличить размер изображения, не растягивая ее (как делает resize()), можно тремя методами.

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

Расширение картинки в Python Pillow

Второй способ — за счет создания нового изображения и вставки в него старого.

Для создания нового изображения нужно использовать метод ‘Image.new()’. В этом методе мы должны указать тип картинки, ее ширину и высоту, а так же цвет. Что бы вставить изображение — используется метод ‘paste()’. В нем указывается отступ формата ‘(верх, лево)’ либо вы можете использовать координаты аналогичные методу ‘crop()’.

В следующем примере мы создадим изображение, которое будет на 50px больше и вставим в него старую картинку. Картинка будет располагаться в 25px от верхнего и левого края:

from PIL import Image image_path = 'F:/hello.png' old_img = Image.open(image_path) # создание нового изображения new_image = Image.new(old_img.mode, (old_img.size[0]+50, old_img.size[1]+50), 'white') # вставляем старой изображение в новое new_image.paste(old_img, (25, 25)) new_image.show() new_image.save('F:/hello3.png') 

Добавление границ и заднего фона в Python Pyllow

Создание границ изображения с ImageOps.expand

Создать границы картинки (расширить) так же можно через метод ImageOps.expand(). Вообще через модуль ‘ImageOps’ можно проделать все шаги описанные выше, но он может не работать с какими-то типами изображений.

В метод ‘expand()’ мы должны передать объект ‘Image’, размер границы и цвет. Пример с результатом аналогичным предыдущему:

from PIL import Image from PIL import ImageOps image_path = 'F:/hello.png' old_img = Image.open(image_path) # создание нового изображения с белым фоном new_image = ImageOps.expand(old_img, border=25, fill=(255,255,255)) new_image.show() new_image.save('F:/hello3.png') 

Источник

Оцените статью