OpenCV: убрать фоновый шум для Tesseract OCR - PullRequest
2 голосов
/ 16 января 2020

У меня есть видео с дрона FPV, из которого мне нужно извлечь координаты GPS. Текст белый, но из-за плохого качества видео кажется серым и голубым. Так как фон меняется, у меня есть некоторые проблемы, потому что в некоторых кадрах фон имеет совершенно другой цвет, а в некоторых кадрах цвет, аналогичный текстовому.

Вот 2 исходных изображения (рамки) из видео :

  1. темный фон Dark background

  2. светлый фон Light background

А вот и код, который я нашел после поиска в Google:

import numpy as np
import cv2
import pytesseract

cap = cv2.VideoCapture('v1.avi')

p = 10000
while(cap.isOpened()):

    ret, frame = cap.read()

    img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    img = img[380:460, 220:640]

    img = cv2.bilateralFilter(img, 9, 27, 27)

    img = cv2.threshold(img, 0, 255,
                        cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    img = cv2.GaussianBlur(img, (9, 9), 0)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    img = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
    img = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)[1]
    img = cv2.dilate(img, kernel)
    img = cv2.threshold(img, 0, 250, cv2.THRESH_BINARY_INV)[1]

    cv2.imshow('frame', img)
    cv2.imshow('or', frame)

    print('\n==============')
    print(pytesseract.image_to_string(img, config='digits'))
    if cv2.waitKey(50) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

А также результаты:

  1. Темный фон Dark background

  2. Светлый фон Light background

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

РЕДАКТИРОВАТЬ: По некоторым причинам я не могу поделиться видео, о котором я писал выше, но вот аналогичное видео с Youtube , и если текст можно извлечь из это видео, я думаю, что этот метод также будет работать для меня или решить, по крайней мере, много проблем:

* 10 41 *

1 Ответ

1 голос
/ 16 января 2020

Я смог заставить что-то работать, используя комбинацию cv2.bilateralFilter и cv2.adaptiveThreshold. Как только фон находится в одном основном BLOB-объекте, числа могут быть извлечены на основе размеров их патчей.

img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# Bilaterial filter and adaptive histogram thresholding to get background into mostly one patch
img = cv2.bilateralFilter(img, 9, 29, 29)
thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 13, 0)

# Add padding to join any background around edges into the same patch 
pad = 2
img_pad = cv2.copyMakeBorder(thresh, pad, pad, pad, pad, cv2.BORDER_CONSTANT, value = 1)

# Label patches and remove padding
ret, markers = cv2.connectedComponents(img_pad)
markers = markers[pad:-pad,pad:-pad]

# Count pixels in each patch
counts = [(markers==i).sum() for i in range(markers.max()+1)]

# Keep patches based on pixel counts
maxCount = 200 # removes large background patches
minCount = 40  # removes specs and centres of numbering
keep = [c<maxCount and c>minCount for c in counts]
output = markers.copy()
for i,k in enumerate(keep):
    output[markers==i] = k

Вот как изображения выглядят на каждом этапе.

Image showing each stage of the analysis

...