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

 

Как стать спецом по анализу данных

Эта статья подготовлена по материалам одного из уроков курса «Машинное обучение и анализ данных», который ты можешь пройти на платформе datasciencecourse.ru. Авторы курса — сотрудники Яндекса, которые доходчиво расскажут обо всех аспектах анализа данных и машинного обучения — от математики и до практического применения в бизнес-процессах. Все, что тебе нужно знать заранее, — это немного математической статистики и основы программирования на Python. Специалисты по data science становятся все более востребованными и получают от 140 тысяч рублей. Спеши вступить в их ряды!

Читатели «Хакера» могут использовать промокод Xakep, чтобы получить 30% скидку при единоразовой оплате. Код действует до 1 февраля 2019 года.

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


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

Из примера выше можно заключить, что для ответа на вопрос, что изображено на рисунке, используется весь жизненный опыт. Например, знание о том, что существует ветер (на картинке его нельзя увидеть явно), что такое транспорт. Чтобы ответить на более сложные вопросы, необходимо знать историю Китая. Соответственно, задача заключается не в том, чтобы смотреть на пиксели, а в использовании знаний.


 

Внутриклассовая изменчивость

Возьмем другой пример. На вопрос, что такое стул, можно ответить первое, что придет в голову. Например, стул — это нечто с четырьмя ножками и спинкой. А как тебе вот такой стул?


Получается, что даже такую вещь, как стул, сложно описать в терминах форм. Стул — это некое концептуальное понятие: что-то, на чем сидят. Можно представить, как сложно объяснить это понятие инопланетному существу, которое не знает даже, что такое сидеть, и не умеет это делать. Прежде чем научить кого-то находить на картинках стул, было бы неплохо, чтобы оно поняло концепцию «сидеть».

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

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

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

 

Задачи компьютерного зрения

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

Первый пример — поиск изображений в интернете. Сейчас существует несколько сервисов, которые позволяют искать картинки. Изначально для поиска использовались текстовые запросы. Некоторое время назад в части из таких сервисов появилась возможность поиска по загруженному изображению. От пользователя требуется загрузить картинку, а сервис будет искать похожие на нее изображения в интернете.

Работает такой поиск следующим образом. Сначала индексируются изображения из интернета. Для них строятся цифровые представления, из них формируется структура данных, по которой можно быстро искать. То же происходит и с пользовательской картинкой — извлекается некое представление о ней, по которому в базе данных ищутся дубликаты или похожие картинки.

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

Вот несколько других примеров.

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

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

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

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

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

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

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

 

«Низкоуровневое» зрение

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

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

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

Самая популярная библиотека для решения задач «низкоуровневого» компьютерного зрения — это OpenCV. В ней содержится огромное количество алгоритмов, есть интерфейсы для многих языков программирования, в том числе С++ и Python. Другая известная библиотека — skimage, она активно используется в скриптах на Python. В примерах дальше мы будем применять OpenCV.

Представление изображения в памяти компьютера
Представление изображения в памяти компьютера

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

 

Арифметические операции

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

В OpenCV используется такое же представление матриц, как в библиотеке NumPy. Это значит, что для них можно использовать стандартные арифметические операции, например сложение.

Однако не все так просто: сложение матриц в NumPy не учитывает переполнение. Для изображений переполнение — это нелогичная операция. Если при сложении двух картинок яркость где-то превысила 255, то, как правило, она должна оставаться равной 255, а не превратиться в 4. Пример ниже показывает, как отличается сложение в NumPy и OpenCV.

import numpy as np
import cv2
x = np.uint8([250])
y = np.uint8([10])
print cv2.add(x,y)

[[255]]

x+y

4

Для примера возьмем картинку.


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

img1 = cv2.imread('imgs/lenna.jpg')
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

Команда cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) будет неоднократно встречаться в дальнейшем. Она используется для преобразования цветовых пространств, в том числе из RGB в серые картинки. После превращения картинки в серую можно прибавить к ней какое-то число.

gray_add = cv2.add(gray, 50)

Такое преобразование эквивалентно увеличению яркости картинки.


Можно не прибавлять, а умножать на некий коэффициент.

gray_mul = cv2.multiply(gray, 1.3)

Умножение картинки эквивалентно увеличению ее контрастности. Можно попробовать использовать больший коэффициент (например, 1.8).


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

 

Эквилизация гистограммы

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

Гистограмма до эквилизации и после
Гистограмма до эквилизации и после

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

equ = cv2.equalizeHist(gray)

Если взять нашу предыдущую картинку, то результат будет выглядеть вот так.


 

Блендинг

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


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

Такое объединение требовательно к качеству вырезания картинки. Если по краям неаккуратно обрезан фон, то будет видна некрасивая белая полоса.

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

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


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


 

Цветовые пространства

Пока что мы говорили только о представлении в RGB, но существуют и другие варианты. Например — HSV.


Компоненты этого пространства — тон (hue), насыщенность (saturation) и значение (value). Это пространство позволяет манипулировать цветом и его насыщенностью по отдельности. Тон обозначает цвет пикселя, он закодирован числом от 0 до 360, как угол на цилиндре. Насыщенность принимает значение 0, если картинка серая.

Если мы работаем с картинкой в HSV, то можем легко сделать ее более насыщенной, умножив соответствующий канал на какой-то коэффициент. Попробуем увеличить насыщенность на 50% (коэффициент 1,5).

hsv = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
hsv[:,:,1] = cv2.multiply(hsv[:,:,1],1.5)
result = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

 

Каскады Хаара — детектор лиц

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

Каскады Хаара
Каскады Хаара

Пиксели, попадающие в белый прямоугольник, берутся со знаком «плюс», в черный — со знаком «минус». Все значения суммируются, и получается одно число. Прямоугольники и коэффициенты для них выбираются с помощью алгоритма AdaBoost. У лица имеются некоторые паттерны, и в итоге каскад фильтров такого рода показывает, есть ли внутри него лицо или нет.

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

 

Сегментация

Задачу сегментации в общем случае решить тоже несложно. Один из способов — отрезать пиксели выше какого-то порога и назначить их объекту, а пиксели ниже порога — фону.

Сегментация изображения
Сегментация изображения

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

img = cv2.imread('coins.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
 

Линейная фильтрация изображений

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

 

Скользящее среднее — свертка

Проще всего объяснить, что такое линейная фильтрация, на примере. Пусть требуется подсчитать среднее в окне 3 × 3 для каждого пикселя. Вычисление среднего можно записать так:


Переписав формулу в следующем виде, можно получить выражение для свертки:


где f — это изображение (двухмерная функция, характеризующая картинку), k, l — координаты пикселя, f — яркость пикселя, h — ядро свертки (матрица 3 × 3, состоящая из единиц).

Если ядро свертки — матрица, то свертка — это скользящее среднее. В OpenCV произвести такую свертку можно следующим образом:

kernel = np.array([[1,1,1],[1,1,1],[1,1,1]],np.float32) / 9
dst = cv2.filter2D(img1,-1,kernel

Картинка при этом становится более размытой. Также размытие изображения можно получать при помощи свертки с гауссовской функцией.

cv2.GaussianBlur(img1,(5,5), 0)
Фото до применения скользящего среднего, после и после применения гауссовского размытия
Фото до применения скользящего среднего, после и после применения гауссовского размытия
 

Детекция границ

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

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

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

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

 

Корреляция

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


В отличие от свертки корреляция используется, чтобы показать меру похожести двух изображений. Это может быть использовано для поиска объектов. Например, требуется найти лицо футболиста.


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

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

 

Резюме

Итак, мы поговорили о проблемах распознавания образов и изучили базовые принципы и методы работы с изображениями. Самые важные компоненты глубоких нейронных сетей состоят как раз из сверток. Поэтому при разработке алгоритмов ML для работы с изображениями, крайне важно понимать, что такое свертка, и для чего она используется. Ну а чтобы ознакомиться с остальными основами data science, ты можешь отправиться на datasciencecourse.ru, пройти все пять курсов и сделать свой проект под присмотром наставника.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии