Классификация изображений в 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
    }
  ]
}