Статьи

Улучшение изображения в Python

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

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

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

Улучшение изображения обычно используется в качестве шага предварительной обработки в фундаментальных шагах, связанных с цифровой обработкой изображения (т.е. сегментация, представление). Существует много методов улучшения изображения, но в этом уроке я расскажу о двух методах: обратное изображение и преобразование степенного закона . Мы посмотрим, как мы можем реализовать их в Python. Итак, начнем!

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

Скажем, что I(i,j) относится к значению интенсивности пикселя, расположенного в (i,j) . Чтобы пояснить здесь немного, значения интенсивности в изображении в градациях серого попадают в диапазон [0,255] , и (i,j) относится к значениям строки и столбца, соответственно. Когда мы применяем обратный оператор изображения к изображению в градациях серого, значение выходного пикселя O(i,j) будет:

1
O(i,j) = 255 — I(i,j)

В настоящее время большинство наших изображений являются цветными изображениями. Эти изображения содержат три канала, красный , зеленый и синий , которые называются изображениями RGB . В этом случае, в отличие от приведенной выше формулы, нам нужно вычесть интенсивность каждого канала из 255. Таким образом, выходное изображение будет иметь следующие значения в пикселях (i,j) :

1
2
3
O_R(i,j) = 255 — R(i,j)
O_G(i,j) = 255 — G(i,j)
OB)i,j) = 255 — B(i,j)

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

Первое, что вам нужно сделать для цветного изображения, это извлечь значение интенсивности каждого пиксельного канала (т.е. RGB). Для этого вы можете использовать библиотеку изображений Python (PIL) . Загрузите образец изображения павиана с baboon.png . Размер изображения 500x500 . Допустим, вы хотите извлечь значения интенсивности красного, зеленого и синего, расположенные в месте расположения пикселя (325, 432) . Это можно сделать следующим образом:

1
2
3
4
from PIL import Image
 
im = Image.open(‘baboon.png’)
print im.getpixel((325,432))

Основываясь на документации, метод getpixel() выполняет следующие действия:

Возвращает значение пикселя в заданной позиции.

Запустив приведенный выше скрипт, вы заметите, что получаете только следующий результат: 138 ! Но где значения интенсивности трех каналов (RGB)? Проблема, кажется, связана с mode считываемого изображения. Проверьте режим, выполнив следующую инструкцию:

1
print im.mode

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

1
rgb_im = im.convert(‘RGB’)

В этом случае вы получите следующее значение: (180, 168, 178) . Это означает, что значения интенсивности для красного, зеленого и синего каналов равны 180, 168 и 178 соответственно.

Чтобы собрать все, что мы описали до сих пор, скрипт Python, который возвращает значения RGB изображения, выглядит следующим образом:

1
2
3
4
5
from PIL import Image
 
im = Image.open(‘baboon.png’)
rgb_im = im.convert(‘RGB’)
print rgb_im.getpixel((325,432))

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

Чтобы распечатать все значения интенсивности для разных каналов каждого пикселя, вы можете сделать следующее:

1
2
3
4
5
6
7
8
9
from PIL import Image
 
im = Image.open(‘baboon.png’)
rgb_im = im.convert(‘RGB’)
width, height = im.size
 
for w in range(width):
    for h in range(height):
        print rgb_im.getpixel((w,h))

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

Давайте посмотрим на пример, который применяет оператор обратного изображения к изображению в градациях серого. Загрузите boat.tiff , который будет служить нашим тестовым изображением в этом разделе. Вот как это выглядит:

Образец изображения лодки для этого урока

Я собираюсь использовать библиотеку scipy для этой задачи. Скрипт Python для применения обратного к изображению оператора на изображении выше должен выглядеть следующим образом:

1
2
3
4
5
6
7
8
9
import scipy.misc
from scipy import misc
from scipy.misc.pilutil import Image
 
im = Image.open(‘boat.tiff’)
im_array = scipy.misc.fromimage(im)
im_inverse = 255 — im_array
im_result = scipy.misc.toimage(im_inverse)
misc.imsave(‘result.tiff’,im_result)

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

Изображение перевернуто

Обратите внимание, что некоторые особенности изображения стали более понятными после применения оператора. Посмотрите, например, на облака и маяк на правильном изображении.

Этот оператор, также называемый гамма-коррекцией , является еще одним оператором, который мы можем использовать для улучшения изображения. Давайте посмотрим на операторное уравнение. В пикселе (i,j) оператор выглядит следующим образом:

1
p(i,j) = kI(i,j)^gamma

I(i,j) — значение интенсивности в местоположении изображения (i,j) ; и k и gamma являются положительными постоянными. Я не буду вдаваться в математические подробности, но я считаю, что вы можете найти подробные объяснения этой темы в книгах по обработке изображений. Однако важно отметить, что в большинстве случаев k=1 , поэтому мы в основном будем менять значение гаммы. Таким образом, приведенное выше уравнение можно уменьшить до:

1
p(i,j) = I(i,j)^gamma

Я собираюсь использовать OpenCV и NumPy здесь. Вы можете проверить мой учебник Представление NumPy, если вам нужно больше узнать о библиотеке. Нашим тестовым изображением снова будет boat.tiff (скачайте его).

Скрипт Python для выполнения оператора Power Law Transformation выглядит следующим образом:

1
2
3
4
5
6
7
8
9
import cv2
import numpy as np
 
im = cv2.imread(‘boat.tiff’)
im = im/255.0
im_power_law_transformation = cv2.pow(im,0.6)
cv2.imshow(‘Original Image’,im)
cv2.imshow(‘Power Law Transformation’,im_power_law_transformation)
cv2.waitKey(0)

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

Преобразование степенного закона

Результат выше был когда gamma = 0.6 . Давайте посмотрим, что произойдет, когда мы увеличим гамму до 1.5 , например:

преобразование степенного закона с более высокой гаммой

Обратите внимание, что при увеличении значения гаммы изображение становится темнее, и наоборот.

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

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

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