Классификация изображений в python
Я ищу метод классификации отсканированных страниц, которые состоят в основном из текста.
Вот подробности моей проблемы. У меня есть большая коллекция отсканированных документов и вам необходимо обнаружить наличие определенных типов страниц в этих документах. Я планирую "лопнуть" документы на свои страницы компонентов (каждый из которых является отдельным изображением) и классифицировать каждое из этих изображений как "A" или "B". Но я не могу понять, как это сделать.
Подробнее:
- У меня есть многочисленные примеры изображений "A" и "B" (страниц), поэтому я могу выполнять контролируемое обучение.
- Мне непонятно, как лучше всего извлекать из этих образов функции для обучения. Например. Каковы эти возможности?
- Страницы иногда слегка вращаются, поэтому было бы замечательно, если бы классификация была несколько нечувствительной к вращению и (в меньшей степени) масштабированию.
- Мне нужно кросс-платформенное решение, в идеале, в чистом питоне или использовании общих библиотек.
- Я думал об использовании OpenCV, но это похоже на "тяжелое" решение.
EDIT:
- Страницы "A" и "B" отличаются тем, что страницы "B" имеют на них формы с одинаковой общей структурой, включая наличие штрих-кода. Страницы "A" являются свободным текстом.
Ответы
Ответ 1
Я отвечу на 3 части, так как ваша проблема явно большая, и я бы настоятельно рекомендовал ручной метод с дешевой рабочей силой, если сбор страниц не превышает 1000.
Часть 1:
Извлечение функций. В поле обнаружения объекта у вас есть очень большой набор функций. Поскольку одним из ваших требований является инвариантность вращения, я бы рекомендовал класс SIFT/SURF. Вы также можете найти подходящие углы Харриса и т.д. Решение о том, какие функции использовать может потребовать экспертных знаний, и если у вас есть вычислительная мощность, я бы рекомендовал создать хороший плавильный котел функций и передать его с помощью оценщика важности оценки классификатора.
Часть 2:
Выбор классификатора - я большой поклонник классификатора Random Forest. Концепция очень проста в понимании и очень гибкая и непараметрическая. Для настройки требуется очень мало параметров, и вы также можете запустить его в режиме выбора параметров во время контролируемого обучения.
Часть 3:
Реализация - Python по сути является языком клея. Чистые реализации python для обработки изображений никогда не будут очень быстрыми. Я рекомендую использовать комбинацию OpenCV для обнаружения функции и R для статистической работы и классификаторов.
Решение может показаться чрезмерно спроектированным, но машинное обучение никогда не было простой задачей, даже когда разница между страницами просто заключается в том, что они являются левыми и правыми страницами книги.
Ответ 2
Во-первых, я хотел бы сказать, что, на мой взгляд, OpenCV - очень хороший инструмент для подобных манипуляций. Кроме того, он имеет интерфейс python, хорошо описанный здесь.
OpenCV сильно оптимизирован, и ваша проблема не из легких.
[GLOBAL EDIT: реорганизация моих идей]
Вот несколько идей о возможностях, которые можно использовать:
-
Для обнаружения штрих-кодов вы должны попытаться сделать дистанционное преобразование (DistTransform в OpenCV), если штрих-код изолирован. Возможно, вы сможете найти интерес с помощью матчей или matchShapes. Я думаю, это возможно, потому что штрих-коды shoudl имеют одинаковую форму (размер и т.д.). Оценка очков интереса может быть использована как функция.
-
Моменты изображения могут быть полезны здесь, потому что у вас есть разные типы глобальных структур. Это может быть достаточно, чтобы провести различие между страницами A и B (см. там для функции openCV) (кстати, вы получите инвариантные дескрипторы: ))
-
Возможно, вам стоит попытаться вычислить vertical gradient
и horizontal gradient
. Штрих-код - это конкретное место, где vertical gradient
== 0 и horizontal gradient
!= 0. Это основное преимущество - низкая стоимость этих операций, так как ваша цель состоит только в том, чтобы проверить, существует ли такая зона на вашей странице. Вы можете найти зону интереса и использовать ее оценку как функцию
После того, как у вас есть свои возможности, вы можете попробовать сделать supervised learning
и проверить обобщение. Ваша проблема требует очень немногих false negative
(потому что вы собираетесь выбросить несколько страниц), поэтому вы должны оценить свою производительность с помощью ROC-кривых и внимательно изучить чувствительность (которая должна быть высокой).
Для классификации вы можете использовать регрессию с штрафом лассо, чтобы найти лучшие функции.
Должность whatnick также дает товарные идеи и другие дескрипторы (возможно, более общие).
Ответ 3
Итак, вы хотите иметь возможность различать два типа страниц с использованием определенных элементов - в основном, наличие штрих-кодов. Существует два шага:
-
извлечение функции (компьютерное зрение): найдите точки интереса или линии, которые будут специфическими чертами штрих-кодов, а не текстом.
-
двоичная классификация (статистическое обучение): определить, есть ли штрих-код или нет, на основе извлеченных функций.
Обращаясь к первому шагу, вам обязательно нужно взглянуть на Преобразование hough. Это идеальное решение для идентификации линий в изображении и может быть полезно для обнаружения штрих-кода. Прочтите эти две страницы, например. Вот примеры с OpenCV.
О втором этапе наиболее полезные классификации будут основаны на:
- k ближайших соседей
- логистическая регрессия
- случайный лес (действительно хорошо реализованный в R, но я не знаю о Python)
Ответ 4
Вы можете попытаться создать модель, загрузив свои данные обучения A и B в demo.nanonets.ai (бесплатно использовать)
1) Загрузите данные для обучения здесь:
demo.nanonets.ai
2) Затем запросите API, используя следующий (код Python):
import requests
import json
import urllib
model_name = "Enter-Your-Model-Name-Here"
url = "https://cdn.pixabay.com/photo/2012/04/24/12/13/letter-39694_960_720.png"
files = {'uploadfile': urllib.urlopen(url).read()}
url = "http://demo.nanonets.ai/classify/?appId="+model_name
r = requests.post(url, files=files)
print json.loads(r.content)
3) ответ выглядит так:
{
"message": "Model trained",
"result": [
{
"label": "A",
"probability": 0.97
},
{
"label": "B",
"probability": 0.03
}
]
}