Предисловие

Жил-был программист, который заявил, что «я могу победить нейронную сеть, используя компьютерное зрение для решения задачи…». Этот пост представляет собой (правдивую) историю этой попытки классификации и рассказывает, какие проблемы были во время этого события и каков был результат.

Соревнование

Потребность в такого рода классификации возникла во время разработки Document Computer Vision Reader (DocCVR). Эта часть программного обеспечения может использовать фотографию документа в качестве входных данных, а затем создавать поля данных документа в структурированном формате в качестве выходных данных. Это достигается с помощью функции OpenCV, которая сопоставляет, а затем вырезает поля из изображения. Таким образом можно «читать», то есть переводить изображение поля в текст с помощью Tesseract.

Среди прочего, DocCVR должен преобразовывать изображение в текст. Это включает в себя идентификатор человека, даты, имена и т. д. Но есть и другие более сложные задачи, такие как преобразование флажков в логические значения. Это означает, что когда тип поля является флажком, значение равно true, если флажок установлен, false, если флажок не установлен, и null, если на изображении нет флажка.

Подготовка

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

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

Итак, теперь у нас есть набор флажков:

  • 1759 изображений, где флажок не установлен
  • 948 изображений, где установлен флажок
  • 1948 изображений, где нельзя однозначно сказать, есть ли флажок

Классификатор 1: фичеинжиниринговый подход

Первая версия детектора флажков основывалась на простых правилах подсчета количества пикселей в изображении. Эта попытка дала нам около 70% успеха, что было слишком мало для наших нужд.

Следующей попыткой было создать детектор флажков с помощью OpenCV GoodFeaturesToTrack (GFTT). Алгоритм GFTT может довольно хорошо находить углы на изображении, и с этими углами можно вычислить возможные области флажков. Как мы видим на изображении ниже, где зеленый контур представляет собой область флажка. Этот алгоритм включает в себя несколько других шагов, которые пытаются отклонить изображения, которые нельзя интерпретировать как флажки, а затем выбрать наиболее очевидный контур, если найдено несколько флажков.

С этим алгоритмом результаты следующие:

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

Объединив эти два алгоритма, мы получили следующие результаты:

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

Классификатор 2: подход с предварительно обученной нейронной сетью

Затем пришло время попробовать ResNet18 и использовать трансферное обучение с нашим набором данных. У нас есть собственная созданная структура для оценки того, как различные гиперпараметры влияют на результат, поэтому было довольно просто запустить несколько итераций, чтобы определить, какие параметры использовать в финальном обучении. Во-первых, набор данных был разделен на наборы обучающих и тестовых данных. Набор обучающих данных содержит около 2900, а набор тестовых данных содержит 931 изображение флажков.

И после десятков итераций результаты выглядят так:

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

Заключение

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

А еще есть время, необходимое для написания необходимого кода. Потребовалось около двух недель, чтобы реализовать логику для алгоритмов OpenCV, по сравнению с несколькими днями, чтобы получить эти результаты от Deep Neural Network (DNN). В основном из-за ранее реализованного ai-dnn-framework.

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

Спасибо

Команде АйРо за данные

В бизнес-подразделение для маркировки

Мике Джуути за опыт в области ИИ и ai-dnn-framework

Адриану Роузброку @pyimagesearch.com за обмен знаниями по OpenCV