обработка изображений для повышения точности Tesseract OCR

Я использую tesseract для преобразования документов в текст. Качество документов колеблется дико, и я ищу советы о том, какая обработка изображений может улучшить результаты. Я заметил, что текст, который сильно пикселизирован, например, сгенерированный факсимильными машинами, особенно сложно обрабатывать tesseract – по-видимому, все эти зубчатые края символов смешивают алгоритмы распознавания фигуры.

Какие методы обработки изображений повысят точность? Я использовал размытие Gaussian, чтобы сгладить пиксельные изображения и увидел небольшое улучшение, но я надеюсь, что существует более конкретный метод, который даст лучшие результаты. Скажем фильтр, который был настроен на черно-белые изображения, которые сглаживали нерегулярные края, а затем фильтр, который увеличивал контрастность, чтобы сделать символы более четкими.

Любые общие советы для тех, кто новичок в обработке изображений?

  1. исправить DPI (при необходимости) 300 DPI минимально
  2. размер шрифта (например, 12 pt должно быть в порядке)
  3. попытайтесь исправить текстовые строки (текст столбца и дьюарпа)
  4. попробуйте исправить освещение изображения (например, нет темной части изображения)
  5. бинаризационное и де-шумовое изображение

Нет универсальной командной строки, которая бы соответствовала всем случаям (иногда вам нужно размыть и заострить изображение). Но вы можете попробовать TEXTCLEANER из Fred’s ImageMagick Scripts .

Если вы не являетесь поклонником командной строки, возможно, вы можете попробовать использовать openource scantailor.sourceforge.net или коммерческий книжный реставратор .

Я отнюдь не эксперт по ОРС. Но на этой неделе мне нужно было преобразовать текст из jpg.

Я начал с раскрашенного RGB 445×747 пикселя jpg. Я тут же попробовал tesseract на этом, и программа практически ничего не конвертировала. Затем я вошел в GIMP и сделал следующее. image> mode> grayscale image> scale image> Фильтры 1191×2000 пикселей> усиление> unsharp mask со значениями радиуса = 6.8, amount = 2.69, threshold = 0 Затем я сохранил как новый jpg со 100% качеством.

Затем Tesseract смог извлечь весь текст в файл .txt

Гипм – твой друг.

Три точки для улучшения читаемости изображения: 1) Измените размер изображения с переменной высотой и шириной (умножьте 0,5 и 1 и 2 с высотой и шириной изображения). 2) Преобразование изображения в формат шкалы серого (черно-белый). 3) Снимите шумовые пиксели и сделайте более четкими (Отфильтруйте изображение).

См. Ниже код:

//Resize public Bitmap Resize(Bitmap bmp, int newWidth, int newHeight) { Bitmap temp = (Bitmap)bmp; Bitmap bmap = new Bitmap(newWidth, newHeight, temp.PixelFormat); double nWidthFactor = (double)temp.Width / (double)newWidth; double nHeightFactor = (double)temp.Height / (double)newHeight; double fx, fy, nx, ny; int cx, cy, fr_x, fr_y; Color color1 = new Color(); Color color2 = new Color(); Color color3 = new Color(); Color color4 = new Color(); byte nRed, nGreen, nBlue; byte bp1, bp2; for (int x = 0; x < bmap.Width; ++x) { for (int y = 0; y < bmap.Height; ++y) { fr_x = (int)Math.Floor(x * nWidthFactor); fr_y = (int)Math.Floor(y * nHeightFactor); cx = fr_x + 1; if (cx >= temp.Width) cx = fr_x; cy = fr_y + 1; if (cy >= temp.Height) cy = fr_y; fx = x * nWidthFactor - fr_x; fy = y * nHeightFactor - fr_y; nx = 1.0 - fx; ny = 1.0 - fy; color1 = temp.GetPixel(fr_x, fr_y); color2 = temp.GetPixel(cx, fr_y); color3 = temp.GetPixel(fr_x, cy); color4 = temp.GetPixel(cx, cy); // Blue bp1 = (byte)(nx * color1.B + fx * color2.B); bp2 = (byte)(nx * color3.B + fx * color4.B); nBlue = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); // Green bp1 = (byte)(nx * color1.G + fx * color2.G); bp2 = (byte)(nx * color3.G + fx * color4.G); nGreen = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); // Red bp1 = (byte)(nx * color1.R + fx * color2.R); bp2 = (byte)(nx * color3.R + fx * color4.R); nRed = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); bmap.SetPixel(x, y, System.Drawing.Color.FromArgb (255, nRed, nGreen, nBlue)); } } bmap = SetGrayscale(bmap); bmap = RemoveNoise(bmap); return bmap; } //SetGrayscale public Bitmap SetGrayscale(Bitmap img) { Bitmap temp = (Bitmap)img; Bitmap bmap = (Bitmap)temp.Clone(); Color c; for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); byte gray = (byte)(.299 * cR + .587 * cG + .114 * cB); bmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray)); } } return (Bitmap)bmap.Clone(); } //RemoveNoise public Bitmap RemoveNoise(Bitmap bmap) { for (var x = 0; x < bmap.Width; x++) { for (var y = 0; y < bmap.Height; y++) { var pixel = bmap.GetPixel(x, y); if (pixel.R < 162 && pixel.G < 162 && pixel.B < 162) bmap.SetPixel(x, y, Color.Black); else if (pixel.R > 162 && pixel.G > 162 && pixel.B > 162) bmap.SetPixel(x, y, Color.White); } } return bmap; } 

ВХОДНОЕ ИЗОБРАЖЕНИЕ
ВХОДНОЕ ИЗОБРАЖЕНИЕ

ВЫХОДНОЕ ИЗОБРАЖЕНИЕ ВЫХОДНОЕ ИЗОБРАЖЕНИЕ

Это несколько назад, но это может быть полезно.

Мой опыт показывает, что изменение размера изображения в памяти перед передачей его в tesseract иногда помогает.

Попробуйте различные способы интерполяции. Сообщение https://stackoverflow.com/a/4756906/146003 мне очень помогло.

Что было ЧРЕЗВЫЧАЙНЫМ ПОМОЩЬЮ для меня на этом пути, являются исходными кодами для проекта Capture2Text. http://sourceforge.net/projects/capture2text/files/Capture2Text/ .

BTW: Престижность его автору за то, что вы делитесь таким кропотливым алгоритмом.

Уделите особое внимание файлу Capture2Text \ SourceCode \ leptonica_util \ leptonica_util.c – вот в чем суть препроцессии изображения для этой утилиты.

Если вы запустите двоичные файлы, вы можете проверить преобразование изображения до / после процесса в папке Capture2Text \ Output \.

PS, упомянутое решение использует Tesseract для OCR и Leptonica для предварительной обработки.

Версия Java для кода Sathyaraj выше:

 // Resize public Bitmap resize(Bitmap img, int newWidth, int newHeight) { Bitmap bmap = img.copy(img.getConfig(), true); double nWidthFactor = (double) img.getWidth() / (double) newWidth; double nHeightFactor = (double) img.getHeight() / (double) newHeight; double fx, fy, nx, ny; int cx, cy, fr_x, fr_y; int color1; int color2; int color3; int color4; byte nRed, nGreen, nBlue; byte bp1, bp2; for (int x = 0; x < bmap.getWidth(); ++x) { for (int y = 0; y < bmap.getHeight(); ++y) { fr_x = (int) Math.floor(x * nWidthFactor); fr_y = (int) Math.floor(y * nHeightFactor); cx = fr_x + 1; if (cx >= img.getWidth()) cx = fr_x; cy = fr_y + 1; if (cy >= img.getHeight()) cy = fr_y; fx = x * nWidthFactor - fr_x; fy = y * nHeightFactor - fr_y; nx = 1.0 - fx; ny = 1.0 - fy; color1 = img.getPixel(fr_x, fr_y); color2 = img.getPixel(cx, fr_y); color3 = img.getPixel(fr_x, cy); color4 = img.getPixel(cx, cy); // Blue bp1 = (byte) (nx * Color.blue(color1) + fx * Color.blue(color2)); bp2 = (byte) (nx * Color.blue(color3) + fx * Color.blue(color4)); nBlue = (byte) (ny * (double) (bp1) + fy * (double) (bp2)); // Green bp1 = (byte) (nx * Color.green(color1) + fx * Color.green(color2)); bp2 = (byte) (nx * Color.green(color3) + fx * Color.green(color4)); nGreen = (byte) (ny * (double) (bp1) + fy * (double) (bp2)); // Red bp1 = (byte) (nx * Color.red(color1) + fx * Color.red(color2)); bp2 = (byte) (nx * Color.red(color3) + fx * Color.red(color4)); nRed = (byte) (ny * (double) (bp1) + fy * (double) (bp2)); bmap.setPixel(x, y, Color.argb(255, nRed, nGreen, nBlue)); } } bmap = setGrayscale(bmap); bmap = removeNoise(bmap); return bmap; } // SetGrayscale private Bitmap setGrayscale(Bitmap img) { Bitmap bmap = img.copy(img.getConfig(), true); int c; for (int i = 0; i < bmap.getWidth(); i++) { for (int j = 0; j < bmap.getHeight(); j++) { c = bmap.getPixel(i, j); byte gray = (byte) (.299 * Color.red(c) + .587 * Color.green(c) + .114 * Color.blue(c)); bmap.setPixel(i, j, Color.argb(255, gray, gray, gray)); } } return bmap; } // RemoveNoise private Bitmap removeNoise(Bitmap bmap) { for (int x = 0; x < bmap.getWidth(); x++) { for (int y = 0; y < bmap.getHeight(); y++) { int pixel = bmap.getPixel(x, y); if (Color.red(pixel) < 162 && Color.green(pixel) < 162 && Color.blue(pixel) < 162) { bmap.setPixel(x, y, Color.BLACK); } } } for (int x = 0; x < bmap.getWidth(); x++) { for (int y = 0; y < bmap.getHeight(); y++) { int pixel = bmap.getPixel(x, y); if (Color.red(pixel) > 162 && Color.green(pixel) > 162 && Color.blue(pixel) > 162) { bmap.setPixel(x, y, Color.WHITE); } } } return bmap; } 

Адаптивное пороговое значение важно, если освещение неравномерно по всему изображению. Моя предварительная обработка с использованием GraphicsMagic упоминается в этом сообщении: https://groups.google.com/forum/#!topic/tesseract-ocr/jONGSChLRv4

GraphicsMagic также имеет функцию -lat для линейного времени Adaptive Threshold, которое я попробую в ближайшее время.

Другой способ определения порога с использованием OpenCV описан здесь: http://docs.opencv.org/trunk/doc/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html

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

В какой-то степени Tesseract автоматически применяет их. Также можно сказать Tesseract написать промежуточное изображение для проверки, то есть проверить, насколько хорошо работает внутренняя обработка изображений (поиск в tessedit_write_images в приведенной выше ссылке).

Что еще более важно, новая система нейронных сетей в Tesseract 4 дает намного лучшие результаты OCR – в целом и особенно для изображений с некоторым шумом. Он включен с помощью --oem 1 , например, как в:

 $ tesseract --oem 1 -l deu page.png result pdf 

(в этом примере выбирается немецкий язык)

Таким образом, имеет смысл сначала проверить, как далеко вы продвигаетесь с новым режимом Tesseract LSTM, прежде чем применять некоторые пользовательские шаги обработки обработки предварительной обработки.

(по состоянию на конец 2017 года Tesseract 4 еще не выпущен как стабильный, но версия разработки может быть использована)

Как правило, я обычно применяю следующие методы предварительной обработки изображений с использованием библиотеки OpenCV:

  1. Изменение размера изображения (рекомендуется, если вы работаете с изображениями с DPI менее 300 dpi):

     img = cv2.resize(img, None, fx=1.2, fy=1.2, interpolation=cv2.INTER_CUBIC) 
  2. Преобразование изображения в оттенки серого:

     img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
  3. Применение дилатации и эрозии для устранения шума (вы можете играть с размером ядра в зависимости от вашего набора данных):

     kernel = np.ones((1, 1), np.uint8) img = cv2.dilate(img, kernel, iterations=1) img = cv2.erode(img, kernel, iterations=1) 
  4. Применение размытия, которое может быть выполнено с использованием одной из следующих строк (каждая из которых имеет свои плюсы и минусы, однако, средний размытие и двусторонний фильтр обычно работают лучше, чем гауссовское размытие):

     cv2.threshold(cv2.GaussianBlur(img, (5, 5), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] cv2.threshold(cv2.bilateralFilter(img, 5, 75, 75), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] cv2.threshold(cv2.medianBlur(img, 3), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] cv2.adaptiveThreshold(cv2.GaussianBlur(img, (5, 5), 0), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2) cv2.adaptiveThreshold(cv2.bilateralFilter(img, 9, 75, 75), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2) cv2.adaptiveThreshold(cv2.medianBlur(img, 3), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2) 

Недавно я написал довольно простое руководство для Tesseract, но он должен позволить вам написать свой первый сценарий OCR и прояснить некоторые препятствия, которые я испытал, когда ситуация была менее ясной, чем хотелось бы в документации.

Если вы хотите проверить их, здесь я разделяю ссылки с вами:

  • Начало работы с Tesseract – Часть I: Введение

  • Начало работы с Tesseract – Часть II: Предварительная обработка изображений

Я сделал это, чтобы получить хорошие результаты из изображения, который имеет не очень маленький текст.

  1. Нанесите смазку на исходное изображение.
  2. Применение адаптивного порога.
  3. Применить эффект заточки.

И если результаты не получат хороших результатов, масштабируйте изображение до 150% или 200%.

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

1) Наличие шума из-за плохого качества изображения / нежелательных элементов / капель в фоновом диапазоне. Для этого требуются некоторые операции предварительной обработки, такие как удаление шума, которые могут быть легко выполнены с использованием гауссовского фильтра или обычных медианных методов фильтрации. Они также доступны в OpenCV.

2) Неправильная ориентация изображения: из-за неправильной ориентации механизм OCR не может правильно отрезать линии и слова в изображении, что дает худшую точность.

3) Наличие строк: при выполнении сегментирования слов или строк механизм OCR иногда также пытается объединить слова и строки вместе и, таким образом, обрабатывать неправильное содержимое и, следовательно, давать неправильные результаты. Существуют и другие проблемы, но они являются основными.

Это сообщение OCR-приложение является примером того, когда некоторая предварительная предварительная обработка изображения и пост-обработка результатов OCR могут применяться для повышения точности распознавания.

  • Поворот изображения в java
  • подключенных компонентов в OpenCV
  • Библиотеки обработки изображений с быстрой кросс-платформенной C / C ++
  • Как заострить изображение в OpenCV?
  • Преобразование RGB в черно-белый в OpenCV
  • Как создать и применить фильтр Гаусса в MATLAB без использования fspecial, imfilter или conv2?
  • Как определить текстовую область из изображения?
  • Загрузка изображений с помощью node.js
  • Компиляция libjpeg
  • Фильтр карты перемещения в OpenCV
  • Создание моего собственного приложения для фото-мозаики с Qt с использованием C ++
  • Давайте будем гением компьютера.