Улучшение порогового результата для Тессеракта - PullRequest
0 голосов
/ 25 октября 2018

Я как-то застрял с этой проблемой, и я знаю, что есть очень много вопросов по поводу переполнения стека, но в моем случае.Ничто не дает ожидаемого результата.

Контекст:

Я использую Android OpenCV вместе с Tesseract, чтобы я мог прочитать область MRZ в паспорте.Когда камера запускается, я передаю входной кадр в AsyncTask, кадр обрабатывается, область MRZ успешно извлекается, я передаю выделенную область MRZ в функцию prepareForOCR (inputImage), которая принимает область MRZ в виде серого Mat и будет выводитьрастровое изображение с пороговым изображением, которое я передам Тессеракту.

Проблема:

Проблема заключается в том, что при пороге изображения я использую адаптивный порог с blockSize = 13и C = 15, но данный результат не всегда одинаков в зависимости от освещения изображения и общих условий, из которых взят кадр.

Что я пробовал:

Сначала я изменяю размер изображения до определенного размера (871,108), поэтому входное изображение всегда одинаково и не зависит от того, какой телефониспользуется.После изменения размера я пытаюсь использовать разные значения BlockSize и C

//toOcr contains the extracted MRZ area
Bitmap toOCRBitmap = Bitmap.createBitmap(bitmap);
Mat inputFrame = new Mat();
Mat toOcr = new Mat();
Utils.bitmapToMat(toOCRBitmap, inputFrame);
Imgproc.cvtColor(inputFrame, inputFrame, Imgproc.COLOR_BGR2GRAY);
TesseractResult lastResult = null;
for (int B = 11; B < 70; B++) {
    for (int C = 11; C < 70; C++){
        if (IsPrime(B) && IsPrime(C)){
            Imgproc.adaptiveThreshold(inputFrame, toOcr, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, B ,C);
            Bitmap toOcrBitmap = OpenCVHelper.getBitmap(toOcr);
            TesseractResult result = TesseractInstance.extractFrame(toOcrBitmap, "ocrba");
            if (result.getMeanConfidence()> 70) {
                if (MrzParser.tryParse(result.getText())){
                    Log.d("Main2Activity", "Best result with " + B + " : " + C);
                    return result;
                }
            }
        }
    }
}

. Используя приведенный ниже код, полученное в результате с пороговым значением полученное изображение представляет собой черно-белое изображение, которое дает достоверность больше 70, я не могу опубликоватьЦелое изображение из соображений конфиденциальности, но вот ограниченный и фиктивный пароль.

Clipped image

From the web

Использование функции MrzParser.tryParse, которая добавляет проверки положения символа иего достоверность в MRZ, я могу исправить некоторые случаи, например, имя, содержащее 8 вместо B, и получить хороший результат, но это занимает так много времени, что является нормальным, поскольку я задаю порог почти 255 изображений в цикле, добавляя к этомувызов Тессеракта.

Я уже пытался получить список значений C и B, который встречается чаще всего, но результаты отличаются.

Вопрос:

Есть ли способ определить C и значение размера блока, чтобы он всегда давал один и тот же результат, возможно, добавляя больше вызовов OpenCV, так что входное изображение, например, увеличение контрастности и т. Д.Я искал в Интернете 2 недели, но не могу найти жизнеспособное решение, это единственное решение, которое дает точные результаты

1 Ответ

0 голосов
/ 11 ноября 2018

Вы можете использовать алгоритм кластеризации для кластеризации пикселей по цвету.Символы темные и в области MRZ имеется хороший контраст, поэтому метод кластеризации, скорее всего, даст вам хорошую сегментацию, если применить его к области MRZ .

Здесь япродемонстрируйте это с помощью областей MRZ, полученных из образцов изображений, которые можно найти в Интернете.

Я использую цветные изображения, применяю некоторое сглаживание, преобразую в Lab цветовое пространство, затем кластеризую a, bданные канала, используя kmeans (k = 2).Код находится в python, но вы можете легко адаптировать его к java.Из-за рандомизированной природы алгоритма kmeans сегментированные символы будут иметь метку 0 или 1. Вы можете легко разобраться в этом, проверив cluster centers.Центр кластера, соответствующий символам, должен иметь значение dark в используемом цветовом пространстве.Я просто использовал цветовое пространство Lab здесь.Вы можете использовать RGB , HSV или даже GREY и посмотреть, какой из них лучше для вас.

После такого сегментирования, я думаю, выможно даже найти хорошие значения для B и C вашего адаптивного порога, используя свойства ширины обводки символов (если вы считаете, что адаптивный порог дает лучшее качество вывода).

import cv2
import numpy as np

im = cv2.imread('mrz1.png')
# convert to Lab
lab = cv2.cvtColor(cv2.GaussianBlur(im, (3, 3), 1), cv2.COLOR_BGR2Lab)

im32f = np.array(im[:, :, 1:3], dtype=np.float32)
k = 2 # 2 clusters
term_crit = (cv2.TERM_CRITERIA_EPS, 30, 0.1)
ret, labels, centers = cv2.kmeans(im32f.reshape([im.shape[0]*im.shape[1], -1]), 
                                  k, None, term_crit, 10, 0)
# segmented image
labels = labels.reshape([im.shape[0], im.shape[1]]) * 255

Некоторые результаты:

1

1-out

2

2-out

3

3-out

4

4-out

...