Время прочтения: 8 мин.

В данной публикации я познакомлю вас с библиотекой Mahotas, которая позволяет обрабатывать изображения. Рассмотрим некоторые методы и функции работы с картинками.

При работе с данными иногда возникает необходимость работать с изображениями. Для этого можно использовать библиотеку Mahotas. Давайте рассмотрим некоторые операции с изображениями, которые можно выполнять с ее помощью.

Установка библиотеки

Установка библиотеки выполняется следующим образом:

pip install mahotas==1.4.13

Также для работы с изображениями нам понадобится библиотека Numpy, так как каждое изображение будет представлено в виде массивов чисел, и модуль библиотеки Matplotlib PyLab, который будем использовать для вывода изображений на экран.

Загрузка и сохранение изображения

Самое простое, что можно сделать, это загрузить изображение. Для этого импортируем библиотеки и используем функцию imread(). Функции imshow() и show() будут необходимы для вывода изображения на экран (рисунок 1).

import mahotas
from pylab import imshow, show
import numpy as np

path_image = r"C:\Users\Admin\Pictures\puppy.jpg"
image = mahotas.imread(path_image)
imshow(image)
show()
Рисунок 1. Загруженное изображение

Для сохранения изображения используется функция imsave(). В качестве параметров передаем путь для сохранения изображения и само изображение.

path_image = r"C:\Users\Admin\Pictures\dog.jpg"
mahotas.imsave(path_image, image)

Изменение цветовой палитры изображения

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

Чтобы узнать размер изображения (размер массивов), можно использовать метод shape. Первое значение – количество пикселей по оси Y, второе значение – по оси Х, третье – количество элементов в каждом массиве для пикселя.

shape = image.shape
print(shape)
Вывод:
(683, 1024, 3)

Полученный размер можно использовать при обрезке изображения (выборке нужной части), если вам необходима только часть картинки. В данном случае мы обрезаем изображение только по оси Х (рисунок 2).

image = image[:, 250:900]
Рисунок 2. Обрезка изображения

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

red, green, blue = image.transpose((2, 0, 1))

# изменим цветовую гамму изображения
new_red = red ** 0.5
new_green = green ** 1.2
new_blue = blue ** 0.8
new_image = mahotas.as_rgb(new_red, new_green, new_blue)
Рисунок 3. Изменения цветовой гаммы изображения

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

Интересная функция rgb2gray() из модуля colors преобразует изображение, усиливая зеленый оттенок картинки, но никак не преобразует изображение в черно-белую палитру.

im_rgb = mahotas.colors.rgb2gray(image)
Рисунок 4. Усиление зеленого канала в изображении

Для получения изображения в сепии используется функция rgb2sepia() (рисунок 5).

im_sepia = mahotas.colors.rgb2sepia(image)
Рисунок 5. Изображение в сепии

Если нужно получить черно-белое изображение, то необходимо установить параметр as_grey, равный True, при загрузке изображения. Если на данной этапе просмотреть изображение, то у нас получится то же самое, что и на рисунке 4. Преобразование значений в массивах изображения к целому типу необходимо в том случае, когда в массивах хранятся вещественные числа — это нужно для получения черно-белого изображения. Далее используем функцию gray() из модуля pylab, и только тогда получаем нужный результат (рисунок 6).

from pylab import imshow, show, gray

image = mahotas.imread(path_image, as_grey=True)
image = image.astype(np.uint8)
gray()
imshow(image)
show()
Рисунок 6. Изображение в черно-белых тонах

Помимо изменения цвета можно преобразовать изображение таким образом, чтобы остались только черный и белый цвета. Для этого нужно из цветного изображения получить черно-белое и использовать преобразование Оцу (Otsu). Преобразование Оцу – это метод, который позволяет выбрать порог яркости, который делит изображение на светлые и темные объекты. Объектом будет группа пикселей, яркость которых превышает полученное значение порога.

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

from pylab import imshow, show, gray

image = mahotas.imread(path_image, as_grey=True)
image = image.astype(np.uint8)
gray()
# вычисление порога яркости
otsu = mahotas.otsu(image)
# выводим только те пиксели, которые ярче полученного порога
imshow(image > otsu)
show()
Рисунок 7. Изображение в черном и белом цветах

Изменение яркости изображения

Яркость изображения также довольно просто изменить. Для этого используем функцию stretch() и в качестве аргумента передаем ей числовое представление изображения в виде массивов, возведенное в степень (на сколько хотим изменить яркость). Чем больше степень, тем ярче (темнее) изображение. На рисунке первое изображение слева – исходное, справа – увеличили яркость в 2 раза, по центру – уменьшили яркость в 2 раза (рисунок 8).

# увеличиваем яркость в 2 раза
image_bright = mahotas.stretch(image ** 2.0)

# уменьшаем яркость в 2 раза
image_bright_1 = mahotas.stretch(image ** 0.5)
Рисунок 8. Изменение яркости изображения

Рисование объектов на изображении

Библиотека Mahotas позволяет нарисовать линию или многоугольник на изображении.

Для рисования линии используем функцию line(). В качестве аргументов передаем две точки с координатами в пикселях (сначала координата Y, потом X), изображение, где будем рисовать линию и цвет в числовом представлении. По умолчанию последний аргумент равен 1 (это черный цвет).

Чтобы нарисовать закрашенный многоугольник, используем функцию fill_polygon(). Аргументами функции являются массив координат многоугольника, изображение, где будем рисовать объект, и цвет фигуры, который также передается в виде числа. На рисунке 9 пример рисования линии и фигуры.

# рисование линии на изображении
mahotas.polygon.line((0, 0), (250, 100), image, 1)

# рисование многоугольника на изображении
mahotas.polygon.fill_polygon([(400, 50), (500, 100), (500, 150), (400, 120)], image, 1)

imshow(image)
show()
Рисунок 9. Рисование объектов на изображении

Выделение объектов и их границ на изображении

Рассмотрим, как можно выделить объекты и их границы на изображении.

Первое, что нужно сделать – это наложить фильтр на изображение. Далее выполним размытие изображения по Гауссу, которое основывается на функции Гаусса, и найдем среднее значение изображения. Среднее значение находится как сумма значений пикселей, деленная на их количество. Использование размытия по Гауссу и деление изображения с использованием среднего значения позволяет уменьшить шум и избавиться от мелких деталей на изображении. Чем больше коэффициент в функции Гаусса, тем меньше будет детализация и тем более гладкими будут контура у выделенных объектов.

path_image = r"C:\Users\Admin\Pictures\puppy.jpg"
image = mahotas.imread(path_image)

# накладываем фильтр на изображение
image = image[:, :, 0]

# размытие изображения
image = mahotas.gaussian_filter(image, 2)

# установка порогового значения 
mean_val = image.mean()
image = (image > mean_val)

После этого можно делить изображение на объекты с помощью функции label(). Эта функция возвращает изображение с выделенными объектами (переменная lable) и количество объектов (переменная objects). На рисунке 10 можно увидеть объекты, которые выделили на изображении. При необходимости можно узнать размер каждого объекта в пикселях, используя функцию labeled_size().

# разметка областей на изображении
lable, objects = mahotas.label(image)
imshow(lable)
show()

# получаем размер каждой области 
sizes = mahotas.labeled.labeled_size(lable)
Рисунок 10. Выделенные объекты на изображении

Поставим перед собой задачу: удалить с изображения объекты, размер которых меньше 1000 пикселей. Сначала выберем такие объекты с помощью Numpy, затем, используя функцию remove_regions(), удалим фрагменты с изображения (рисунок 11).

# выбираем области для удаления
objects_to_remove = np.where(sizes < 1000)

# удаляем объекты
image_without_objects = mahotas.labeled.remove_regions(lable, objects_to_remove)
imshow(image_without_objects)
show()
Рисунок 11. Изображение после удаления объектов

Теперь после удаления небольших объектов выделим границы оставшихся (рисунок 12). Это можно сделать с помощью функции borders().

# выделяем границы объектов
border_image = mahotas.labeled.borders(image_without_objects)
imshow(border_image)
show()
Рисунок 12. Выделение границ объектов

Заключение

В данной публикации были рассмотрены некоторые функции и методы для работы с изображениями, а именно:

  • загрузка и сохранение иллюстрации;
  • преобразование цветного изображения в черно-белое, сепию, усиление зеленого цвета на картинке;
  • произвольное изменение красного, зеленого и синего цветов;
  • получение изображения в черном и белом цветах с использованием метода Оцу;
  • рисование линий и многоугольников;
  • выделение, удаление и получение контуров объектов на изображении.