【Перевод】Научит вас использовать инструмент обработки изображений OpenCV

OpenCV

Автор: Мухаммед Джунаид Халид.

Перевод: Лао Ци

Рекомендации по книгам, связанным с этой статьей: "Подготовка данных и проектирование признаков"


резюме

В этой статье мы узнаем, как использовать язык Python для обработки изображений, мы не будем ограничиваться одной библиотекой или фреймворком, однако есть одна библиотека, которая будет наиболее используемой, и это OpenCV. Мы начнем с обсуждения некоторой обработки изображений, а затем перейдем к различным приложениям/сценариям, в которых используется обработка изображений. Давайте начнем!

Что такое обработка изображений?

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

Зачем нужна обработка изображений?

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

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

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

Предварительные знания

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

Прежде всего, у вас должны быть определенные навыки программирования. В этой статье используется язык Python. Если вы еще не освоили этот язык, рекомендуется прочитать «Изучаем Python по-старому: простое введение» или «Практическое руководство по Python University». ".

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

Кроме того, было бы полезно, если бы вы уже знакомились с основами OpenCV или освоили их. Но это не обязательно.

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

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

Установить

Примечание: Поскольку мы собираемся использовать OpenCV с Python, вы должны уметь его использовать.Рекомендуются книги по Python. Далее описаны способы установки OpenCV в разных операционных системах по очереди:

  • Windows
$ pip install opencv-python
  • MacOS
$ brew install opencv3 --with-contrib --with-python3
  • Linux
$ sudo apt-get install libopencv-dev python-opencv

Чтобы проверить, прошла ли установка успешно, выполните следующую команду в интерактивном режиме Python:

import cv2

Основные основы

Перед тем, как приступить к обработке изображения, требуется некоторая подготовка.

В этой статье мы будем использовать следующие изображения:

Примечание. Изображение было масштабировано для отображения в этой статье, но исходный размер изображения, которое мы использовали, был примерно 1180x786.

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

найти детали изображения

использоватьimread()После того, как функция загрузит изображение, мы можем получить некоторые его простые свойства, такие как количество и размеры пикселей:

import cv2

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

print("Image Properties")
print("- Number of Pixels: " + str(img.size))
print("- Shape/Dimensions: " + str(img.shape))

Output:

Image Properties
- Number of Pixels: 2782440
- Shape/Dimensions: (1180, 786, 3)

Разделить изображение на отдельные каналы

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

from google.colab.patches import cv2_imshow

blue, green, red = cv2.split(img)    # Split the image into its channels
img_gs = cv2.imread('rose.jpg', cv2.IMREAD_GRAYSCALE)    # Convert image to grayscale

cv2_imshow(red) # Display the red channel in the image
cv2_imshow(blue) # Display the red channel in the image
cv2_imshow(green) # Display the red channel in the image
cv2_imshow(img_gs) # Display the grayscale version of image

Для простоты мы показываем только изображения в градациях серого.

порог изображения

Концепция порогов очень проста. Как обсуждалось выше в разделе «Представление изображения», значение пикселя может быть любым от 0 до 255. Предположим, мы хотим преобразовать изображение в бинаризацию, то есть присвоить пикселю значение 0 или 1. Для этого мы можем установить пороги. Например, если пороговое значение (T) равно 125, то всем пикселям больше 125 будет присвоено значение 1, а всем пикселям меньше или равно этому значению будет присвоено значение 0. Ниже мы рассмотрим код, чтобы лучше понять его.

Преобразуйте изображение ниже, используя описанный выше метод:

import cv2

# Read image
img = cv2.imread('image.png', 0)

# Perform binary thresholding on the image with T = 125
r, threshold = cv2.threshold(img, 125, 255, cv2.THRESH_BINARY)
cv2_imshow(threshold)

вывод:

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

применение

1: удалить шум с изображения

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

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

Существует множество различных типов шума, таких как шум Гаусса, шум соли и перца и т. д. Мы можем удалить шум с изображения или, по крайней мере, свести к минимуму его влияние, применив фильтр. Есть также много вариантов фильтров, каждый из которых имеет свои преимущества. Таким образом, для определенного типа шума один всегда является лучшим.

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

import numpy as np

# Adding salt & pepper noise to an image

def salt_pepper(prob):
      # Extract image dimensions
      row, col = img_gs.shape

      # Declare salt & pepper noise ratio
      s_vs_p = 0.5
      output = np.copy(img_gs)

      # Apply salt noise on each pixel individually
      num_salt = np.ceil(prob * img_gs.size * s_vs_p)
      coords = [np.random.randint(0, i - 1, int(num_salt))
            for i in img_gs.shape]
      output[coords] = 1

      # Apply pepper noise on each pixel individually
      num_pepper = np.ceil(prob * img_gs.size * (1. - s_vs_p))
      coords = [np.random.randint(0, i - 1, int(num_pepper))
            for i in img_gs.shape]
      output[coords] = 0
      cv2_imshow(output)

      return output

# Call salt & pepper function with probability = 0.5
# on the grayscale image of rose
sp_05 = salt_pepper(0.5)

# Store the resultant image as 'sp_05.jpg'
cv2.imwrite('sp_05.jpg', sp_05)

Хорошо, мы добавили шум к изображению розы, вот как это теперь выглядит:

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

фильтр резкости

# Create our sharpening kernel, the sum of all values must equal to one for uniformity
kernel_sharpening = np.array([[-1,-1,-1],
                              [-1, 9,-1],
                              [-1,-1,-1]])

# Applying the sharpening kernel to the grayscale image & displaying it.
print("\n\n--- Effects on S&P Noise Image with Probability 0.5 ---\n\n")

# Applying filter on image with salt & pepper noise
sharpened_img = cv2.filter2D(sp_05, -1, kernel_sharpening)
cv2_imshow(sharpened_img)

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

Выход фильтра резкости:

медианный фильтр

from scipy.ndimage import maximum_filter, minimum_filter

def midpoint(img):
    maxf = maximum_filter(img, (3, 3))
    minf = minimum_filter(img, (3, 3))
    midpoint = (maxf + minf) / 2
    cv2_imshow(midpoint)

print("\n\n---Effects on S&P Noise Image with Probability 0.5---\n\n")
midpoint(sp_05)

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

Выход медианного фильтра:

Фильтр обратного гармонического среднего

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

def contraharmonic_mean(img, size, Q):
    num = np.power(img, Q + 1)
    denom = np.power(img, Q)
    kernel = np.full(size, 1.0)
    result = cv2.filter2D(num, -1, kernel) / cv2.filter2D(denom, -1, kernel)
    return result

print("\n\n--- Effects on S&P Noise Image with Probability 0.5 ---\n\n")
cv2_imshow(contraharmonic_mean(sp_05, (3,3), 0.5))

Примените фильтр обратного среднего гармонического к изображению с шумом из соли и перца (En. Wikipedia.org/wiki/contra…) и полученное изображение показано ниже. Сравнивая с исходным изображением в градациях серого, мы видим, что оно почти идеально воспроизводит исходное изображение. Его уровень интенсивности или яркости такой же, как у исходного изображения, и он подчеркивает блики на розе. Таким образом, мы можем заключить, что фильтр обратного гармонического среднего очень эффективен в борьбе с шумом соли и перца.

Выход обратного гармонического среднего фильтра:

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

2: Используйте оператор Canny для обнаружения границ

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

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

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

Для этого классификатора кошек, просто взяв в качестве примера изображение кошки, вот изображение, которое мы будем использовать:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# Declaring the output graph's size
plt.figure(figsize=(16, 16))

# Convert image to grayscale
img_gs = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imwrite('gs.jpg', img_gs)

# Apply canny edge detector algorithm on the image to find edges
edges = cv2.Canny(img_gs, 100,200)

# Plot the original image against the edges
plt.subplot(121), plt.imshow(img_gs)
plt.title('Original Gray Scale Image')
plt.subplot(122), plt.imshow(edges)
plt.title('Edge Image')

# Display the two images
plt.show()

Выход обнаружения края:

Как видите, часть изображения, которая содержит объект (в данном случае кошку), была отмечена или отделена пунктирной линией с помощью обнаружения краев. Теперь вам должно быть интересно, что такое оператор Кэнни для обнаружения границ и как он работает? Обсудите это сейчас.

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

Наконец, гистерезисная пороговая обработка; выше мы сказали, что будет пик значения первой производной на краю, но мы не сказали: насколько высоким должен быть этот пик, чтобы классифицировать его как край — это называется пороговой обработкой Ранее в этой статье мы обсуждали, что такое простой порог. Метод порога гистерезиса является усовершенствованием на этой основе, в котором вместо одного порога используются два порога. Причина этого заключается в том, что если порог слишком высок, мы можем пропустить некоторые реальные края (истинные отрицания), а если порог слишком низок, мы получим много точек, которые классифицируются как края, а не на самом деле края (ложные срабатывания). ) пример). Один порог установлен на высокий уровень, а другой установлен на низкий уровень, чтобы идентифицировать все точки выше «высокого порога» как ребра, затем оцениваются все точки выше «нижнего порога», но ниже «высокого порога»; точки на ребрах После определения точки закрываются. до или рядом с граничной точкой также определяются как кромка, а остальные точки отбрасываются.

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

Примечание переводчика:Оператор Кэнни — это многоуровневый алгоритм обнаружения границ, разработанный австралийским ученым-компьютерщиком Джоном Ф. Кэнни в 1986 году, целью которого является поиск оптимальной границы.

в заключении

В этой статье мы узнали, как установить OpenCV на разные платформы, такие как Windows, MacOS и Linux, и как убедиться, что установка прошла успешно. OpenCV — самая популярная библиотека обработки изображений на Python.

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

Кроме того, мы увидели, как обработка изображений играет неотъемлемую роль в высокопроизводительных приложениях, таких как обнаружение или классификация объектов. Обратите внимание, что эта статья — лишь верхушка айсберга, о цифровой обработке изображений рассказывается гораздо больше, чем в одной короткой статье. Обратите внимание на паблик WeChat «Laoqi Classroom», где также будут публиковаться статьи по обработке изображений.

Оригинальная ссылка:stack abuse.com/intro duct IO…

Найдите общедоступный номер технических вопросов и ответов: класс Лао Ци

Ответ в публичном аккаунте:Лао Ципросмотреть все статьи, книги, курсы.