Введение. Задача оффлайн распознавания рукописного текста, как правило, состоит из нескольких этапов: предварительная обработка, сегментация, извлечение признаков, классификация и обработка результатов.
В рамках данной статьи сосредоточимся на первых двух этапах. На этапе предварительной обработки происходит обработка изображения с целью повышения его качества и приведения его к виду, удобному для сегментации. Этап сегментации подразумевает выделение текста на изображении и его разделение на составные части. Обычно текст обрабатывается иерархически: сначала выделяются отдельные строки, затем отдельные слова, затем символы или части символов.
Для реализации двух первых этапов оффлайн распознавания рукописного текста можно воспользоваться таким инструментом, как OpenCV.
OpenCV представляет собой библиотеку компьютерного зрения с открытым исходным кодом, которая разработана компанией Intel на языке программирования C/C++. Также существуют версии этой библиотеки и для других языков, таких как Python, Java, С#, MatLab и многих других. В данной библиотеке реализовано множество алгоритмов следующих типов [1, 2]:
- Распознавание объектов;
- Распознавание печатного текста;
- Устранение искажений;
- Выявление сходства и формы объектов;
- Отслеживание перемещение объекта;
- Распознавание движений, жестов.
Предварительная обработка изображения. Этап предварительной обработки изображения обычно состоит из следующих задач [3, 4]:
- Преобразование изображения в градации серого;
- Удаление дефектов.
Рис. 1. Карта проекта OpenCV.
Изображение в OpenCV представляется с помощью класса Image [5]. При создании объекта этого класса необходимо указать путь к изображению. Для решения задачи преобразования изображения в градации серого достаточно вызвать метод Convert и указать конечный цвет изображения, в данном случае цвет Gray. Результат обработки можно увидеть на Рис.2.
Пример исходного кода, написанного на языке C#, с помощью библиотеки Emgu.CV, которая является оберткой под .NET платформу над оригинальной библиотекой OpenCV:
var img = new Image<Bgr, byte>(filePath);
var grayImage = img.Convert<Gray, byte>();
Рис. 2. Преобразование изображения в градации серого.
Удаление дефектов подразумевает собой применение различных фильтров для удаления шумов. Наиболее часто используемыми фильтрами являются фильтр Гаусса для подавления высокочастотного шума и медианный фильтр для удаления шума «соль и перец». Реализации этих фильтров также есть в OpenCV.
Для использования фильтра Гаусса достаточно воспользоваться функцией GaussianBlur поместив в качестве параметров входное и выходное изображения, размер ядра Гаусса, величины отклонения ядра Гаусса по осям X и Y, а также метод экстраполяции пикселей [6]. Под ядром Гаусса понимается матрица свертки, которая помогает для каждого пикселя изображения рассчитать средневзвешенное значение соседних пикселей. В результате чего все зашумленные пиксели (яркость которых сильно отличается от яркости соседних пикселей) примут усредненное значение. Ширина и высота ядра могут отличаться, но они оба должны быть положительными и нечетными. Также они могут быть равны 0, что будет означать, что размер ядра будет рассчитываться исходя из величины отклонения ядра Гаусса.
В свою очередь для использования медианного фильтра необходимо воспользоваться функцией MedianBlur поместив в качестве параметров входное и выходное изображения, размер окна (апертуры), которое должно быть нечётным. Результат применения медианного фильтра можно увидеть на Рис.3.
Пример исходного кода:
CvInvoke.MedianBlur(grayImage, grayImage, 5);
CvInvoke.GaussianBlur(grayImage, grayImage, new Size(5, 5), 1.5, 0, BorderType.Replicate);
Выделение слов на изображении. Как уже было сказано выше, следующим этапом в оффлайн распознавании рукописного текста является этап сегментации. Основная задача этого этапа – выделение текста на изображении. Если пренебречь тем, что рукописный текст может быть написан под различным наклоном, то с помощью OpenCV можно сразу выделять строки и слова, находящиеся в каждой из строк.
Рис. 3. Результат применения медианного фильтра.
Процесс выделения слов при помощи OpenCV можно разделить на следующие этапы:
- Пороговая бинаризация изображения;
- Применение операции морфологического замыкания;
- Выделение границ слов.
Метод пороговой бинаризации осуществляется при помощи функции Threshold, которая принимает на вход изображение в градациях серого, выходное изображение, величину порога и алгоритм вычисления порога. Наиболее известным алгоритмом вычисления порога является метод Оцу [7]. В результате бинаризации получаем изображения белого текста на черном фоне (Рис. 4).
Пример исходного кода:
var thresholdImage = new Image<Gray, byte>(grayImage.Size);
CvInvoke.Threshold(grayImage, thresholdImage, 0, 255, ThresholdType.Otsu);
Для того чтобы на последнем этапе выделить слова с изображения, необходимо воспользоваться морфологической операцией замыкания [8]. Для этого служит функция MorphologyEx, принимающая на вход изображение, полученное на предыдущем этапе, выходное изображение, тип морфологической операции (в данном случае операция замыкания) и структурный элемент, с которым будет осуществляться операция. В качестве структурного элемента обычно используют прямоугольник. Результат применения морфологической операции замыкания можно увидеть на Рис. 5.
Пример исходного кода:
var element = CvInvoke.GetStructuringElement( ElementShape.Rectangle, new Size(5, 5), new Point(0, 0));
CvInvoke.MorphologyEx(thresholdImage, thresholdImage, MorphOp.Close, element, new Point(-1, -1), 12, BorderType.Default, new MCvScalar());
Рис. 4. Результат пороговой бинаризации.
Наконец, на последнем этапе выделяются слова на изображении. Для этого используются функции FindContours, которая находит все контуры слов на бинарном изображении и функция BoundingRectangle, которая возвращает ограничивающий прямоугольник для каждого слова на основе контура. В результате, с помощью этих прямоугольников мы можем выделить слова на конечном изображении (Рис. 6).
Пример исходного кода:
var contours = new VectorOfVectorOfPoint();
var rects = new List<Rectangle>();
CvInvoke.FindContours(thresholdImage, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);
for (var i = 0; i < contours.Size; i++)
{
var approxContour = new VectorOfPoint();
CvInvoke.ApproxPolyDP(contours[i], approxContour, 0.005, true);
if (CvInvoke.ContourArea(approxContour) > 100)
{
var boundingRectangle = CvInvoke.BoundingRectangle (approxContour);
rects.Add(boundingRectangle);
}
}
Рис. 5. Результат морфологической операции замыкания.
Рис. 6. Выделенные слова на изображении.
Заключение. Таким образом, в данной статье было рассмотрено использование открытой библиотеки OpenCV для предобработки изображения и выделения слов на изображении в рамках задачи оффлайн распознавания рукописного текста. Данная библиотека справляется с этой задачей достаточно качественно и быстро.