Чистые текстовые изображения с OpenCV для чтения OCR - PullRequest
0 голосов
/ 22 января 2020

Я получил несколько изображений, которые нужно обработать, чтобы распознать некоторую информацию из них. Вот оригиналы:

оригинал 1

original 1

оригинал 2

original 2

оригинал 3

original 3

оригинал 4

original 4

После обработки их с этим кодом:

img = cv2.imread('original_1.jpg', 0) 
ret,thresh = cv2.threshold(img,55,255,cv2.THRESH_BINARY)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_RECT,(2,2)))
cv2.imwrite('result_1.jpg', opening)

Я получаю эти результаты:

результат 1

result 1

результат 2

result 2

результат 3

result 3

результат 4

result 4

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

Есть предложения, как очистить фон?

Ответы [ 2 ]

0 голосов
/ 23 января 2020

MH304 ответ очень приятный и прямой. В случае, если вы не можете использовать морфологию или размытие, чтобы получить более чистое изображение, попробуйте использовать «Фильтр области». То есть фильтруйте каждый большой объект, который не имеет минимальной площади.

Используйте opencv connectedComponentsWithStats , вот реализация C ++ очень простого c фильтра области:

cv::Mat outputLabels, stats, img_color, centroids;

int numberofComponents = cv::connectedComponentsWithStats(bwImage, outputLabels, 
stats, centroids, connectivity);

std::vector<cv::Vec3b> colors(numberofComponents+1);
colors[i] = cv::Vec3b(rand()%256, rand()%256, rand()%256);

//do not count the original background-> label = 0:
colors[0] = cv::Vec3b(0,0,0);

//Area threshold:
int minArea = 10; //10 px

for( int i = 1; i <= numberofComponents; i++ ) {

    //get the area of the current blob:
    auto blobArea = stats.at<int>(i-1, cv::CC_STAT_AREA);

    //apply the area filter:
    if ( blobArea < minArea )
    {
        //filter blob below minimum area:
        //small regions are painted with (ridiculous) pink color
        colors[i-1] = cv::Vec3b(248,48,213);

    }

}

Используя фильтр области, я получаю этот результат на вашем самом шумном изображении:

enter image description here

** Дополнительная информация:

По сути, алгоритм выглядит следующим образом:

  • Передача двоичного изображения в connectedComponentsWithStats . Функция рассчитает количество подключенных компонентов, матрицу меток и дополнительную матрицу с статистикой - включая область BLOB-объектов.

  • Подготовьте цветовой вектор размером « numberOfcomponents ”, это поможет визуализировать капли, которые мы на самом деле фильтруем. Цвета генерируются случайным образом с помощью функции rand . В диапазоне от 0 до 255, 3 значения для каждого пикселя: BGR.

  • Учтите, что фон окрашен в черный цвет, поэтому игнорируйте этот «связанный компонент» и его цвет (черный).

  • Установите порог области. Все капли или пиксели ниже этой области будут окрашены (смешно) в розовый цвет.

  • L oop через все найденные подключенные компоненты (BLOB-объекты), извлеките область для текущего BLOB-объекта через матрицу статистики и сравните ее с пороговым значением области.

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

0 голосов
/ 22 января 2020

Маленький медианный фильтр получил мне этот результат:

enter image description here

Код (Opencv C ++):

Mat im = imread("E:/4.jpg",0);
medianBlur(im, im, 3);
threshold(im, im, 70, 255, THRESH_BINARY_INV);
imshow("1", im);
waitKey(0);
...