В этом блоге рассматриваются алгоритмы, используемые для автоматизации решения CAPTCHA. Описание этого дано в моем предыдущем блоге:



Этот проект реализован с использованием OpenCV в сочетании с C++. Поэтому некоторые используемые здесь термины на самом деле являются функциями, определенными в библиотеке OpenCV.

Шаги

Следующие шаги выполняются для решения любых текстовых CAPTCHA.

Удаление шума и бинаризация

Обнаружение текстовой области

Сегментация

Распознавание символов

Удаление шума и бинаризация

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

Mat src = imread("captcha.png",IMREAD_COLOR);

imshow("Исходное изображение", src);// Показать исходное изображение

cv::cvtColor(src, matGrayscale, CV_BGR2GRAY)//преобразование в оттенки серого

cv::GaussianBlur(matGrayscale,matBlurred,cv::Size(5, 5),0);

// параметры - входное изображение

// выходное изображение

// сглаживание ширины и высоты окна в пикселях

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

// фильтруем изображение из оттенков серого в черно-белое

cv::adaptiveThreshold(matBlurred,matThresh,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY_INV,11,2);

// параметры - входное изображение

// выходное изображение

// делаем пиксели, прошедшие порог, полностью белыми

// использовать гауссовское, а не среднее, кажется, дает лучшие результаты

// инвертировать, чтобы передний план был белым, а фон черным

// размер окрестности пикселя, используемый для вычисления порогового значения

// константа вычитается из среднего или средневзвешенного значения

Сегментация

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

for (int i = 0; i ‹ ptContours.size(); i++)

{// для каждого контура

если (cv::contourArea(ptContours[i]) › MIN_CONTOUR_AREA)

{// если контур достаточно велик, чтобы рассмотреть

cv::RectboundingRect =cv::boundingRect(ptContours[i]);

// получаем ограничивающий прямоугольник

cv::rectangle(src, boundingRect, cv::Scalar(0, 0, 255), 1);

// рисуем красный прямоугольник вокруг каждого контура, когда запрашиваем ввод у пользователя

cv::Mat matROI = matThresh(boundingRect);

// получаем изображение ROI ограничивающего прямоугольника

cv::Mat matROIResized;

cv::resize(matROI, matROIResized, cv::Size(RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT));

// изменить размер изображения, это будет более удобно для распознавания и хранения

}

}

Распознавание символов

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

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

Img_mat=Двоичный(captcha.png)

Img_mat = Оттенки серого (Img_mat)

Рассчитать (порог T)

для каждого пикселя(x,y) € Img_mat do

если(color_intensity[x,y] › T ), то

color_intensity[x,y]=белый

еще

color_intensity[x,y]=черный

конец для

Чтобы получить каждый символ из Img_mat в отдельном блоке с помощью подключенного компонента,

для каждого символа с пиксельным кластером (x,y) € Img_mat && color_intensity[x,y]=white from Img_mat do

Верхний левый (х, у) = мин (х), мин (у)

Верхний правый (x, y) = max (x), min (y)

Нижний левый (х, у) = мин (х), макс (у)

Нижний правый (x, y) = max (x), max (y)

Drawcontour (верхний левый, верхний правый, нижний левый нижний правый)

Изменить размер прямоугольника на фиксированные размеры по умолчанию

конец для

Для распознавания символов из CAPTCHA классификатор сравнивает текущий блок символов с сохраненными данными и возвращает соответствующее значение.

Открыть (Training_data.txt, ПРОЧИТАТЬ)

для каждого прямоугольника в Img_mat делаем

для каждых данных в Training_data.txt выполните

соответствие= Классификатор()

если(максимальное_совпадение ‹ совпадение) тогда

максимальное_соответствие = совпадение

конец для

string_append (classification_char)

конец для

Возвращаемая строка

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