2012-02-28 4 views
99

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

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

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

ответ

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

Там нет универсальной командной строки, которая будет соответствовать всем делам (иногда вам нужно б lur и sharpen image). Но вы можете попробовать TEXTCLEANER from Fred's ImageMagick Scripts.

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

+5

И проиллюстрировано руководство о том, как это сделать: https://code.google.com/p/tesseract-ocr/wiki/ImproveQuality – iljau

+2

Обратите внимание, что связанный скрипт выглядит только как linux. –

+0

@ZoranPavlovic вы правы. Ссылка предназначена только для Linux. – Prashant

56

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

Я начал с раскрашенного RGB 445x747 пикселя jpg. Я тут же попробовал tesseract, и программа практически ничего не конвертировала. Затем я вошел в GIMP и сделал следующее. изображение> режим> оттенки серого изображение> масштабное изображение> 1191x2000 пикселей фильтры> усиление> нерезкая маска со значениями радиуса = 6.8, amount = 2.69, threshold = 0 Затем я сохранил как новый jpg со 100% качеством.

Тессеракт затем смог извлечь весь текст в текстовый файл

Gimp является вашим другом.

+7

+1 Я следил за твоими шагами, и у меня было хорошее улучшение. Спасибо – onof

+1

У меня также создается впечатление, что Tesseract работает лучше, если вы конвертируете вход в файл TIFF и даете Tesseract TIFF (вместо того, чтобы просить Tesseract выполнить преобразование для вас). ImageMagick может выполнить преобразование для вас. Это мое анекдотическое впечатление, но я не проверял его тщательно, так что это может быть неправильно. –

+0

+1 Фильтр «нерезкой маски» действительно сделал мой день. Еще один шаг, который помог мне: используя инструмент «Нечеткий выбор», выберите фон, затем нажмите «Del», чтобы уменьшить его. – Davide

15

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

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

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

+1

Если я могу спросить: почему нисходящий? – Atmocreations

13

Что было Чрезвычайно полезным для меня на этом пути являются исходники для проекта Capture2Text. http://sourceforge.net/projects/capture2text/files/Capture2Text/.

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

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

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

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

22

Три точки для улучшения читаемости изображения: 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 * c.R + .587 * c.G + .114 * c.B); 

        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; 
     } 

ВХОД IMAGE
INPUT IMAGE

ВЫВОД IMAGE OUTPUT IMAGE

+0

это весь *** код ***? – Kiquenet

+0

Да. Мы должны передать требуемый параметр для метода Resize, он будет предусматривать изменение размера, операцию SetGrayscale и RemoveNoise, а затем вернуть выходное изображение с лучшей читабельностью. –

+0

Пробовал этот подход по набору файлов и сравнивал с исходным результатом. В некоторых ограниченных случаях это дает лучший результат, в основном было небольшое снижение качества выходного текста. Таким образом, это не похоже на универсальное решение. – Bryn

6

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

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

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

+2

Ссылка OpenCV изменена. В документации OpenCV это [Учебники по OpenCV-Python> Обработка изображений в OpenCV> Порог изображения] (http://docs.opencv.org/master/d7/d4d/tutorial_py_thresholding.html) – richk

12

Java версия для кода Сатяраджа в выше:

// 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; 
} 
+0

Каков ваш класс для Bitmap? Bitmap не найден в Java (он находится в Android изначально). –

+0

Этот метод исключает: вызван: java.lang.IllegalArgumentException: y должно быть Nativ

1

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

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

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

3

Документация Tesseract содержит подробную информацию о how to improve the OCR quality с помощью шагов обработки изображений.

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

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

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

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

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

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

2

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

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

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

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

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