Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
518 views
in Technique[技术] by (71.8m points)

python - Background image cleaning for OCR

Through tesseract-OCR I am trying to extract text from the following images with a red background.

enter image description here

I have problems extracting the text in boxes B and D because there are vertical lines. How can I clean the background like this:

input:

enter image description here

output:

enter image description here

some idea? The image without boxes: enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here are two methods to clean the image using Python OpenCV

Method #1: Numpy thresholding

Since the vertical lines, horizontal lines, and the background are in red we can take advantage of this and use Numpy thresholding to change all red pixels above a threshold to white.

enter image description here

import cv2
import numpy as np

image = cv2.imread('1.jpg')

image[np.where((image > [0,0,105]).all(axis=2))] = [255,255,255]

cv2.imshow('image', image)
cv2.waitKey()

Method #2: Traditional image processing

For a more general approach if the lines were not red we can use simple image processing techniques to clean the image. To remove the vertical and horizontal lines we can construct special kernels to isolate the lines and remove them using masking and bitwise operations. Once the lines are removed, we can use thresholding, morphological operations, and contour filtering to remove the red background. Here's a visualization of the process


First we construct vertical and horizontal kernels then cv2.morphologyEx() to detect the lines. From here we have individual masks of the horizontal and vertical lines then bitwise-or the two masks to obtain a mask with all lines to remove. Next we bitwise-or with the original image to remove all lines

enter image description here enter image description here enter image description here enter image description here

Now that the lines are removed, we can work on removing the red background. We threshold to obtain a binary image and perform morphological operations to smooth the text

enter image description here

There are still little dots so to remove them, we find contours and filter using a minimum threshold area to remove the small noise

enter image description here

Finally we invert the image to get our result

enter image description here

import cv2

image = cv2.imread('1.jpg')

# Remove vertical and horizontal lines
kernel_vertical = cv2.getStructuringElement(cv2.MORPH_RECT, (1,50))
temp1 = 255 - cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel_vertical)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50,1))
temp2 = 255 - cv2.morphologyEx(image, cv2.MORPH_CLOSE, horizontal_kernel)
temp3 = cv2.add(temp1, temp2)
removed = cv2.add(temp3, image)

# Threshold and perform morphological operations
gray = cv2.cvtColor(removed, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)

# Filter using contour area and remove small noise
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 10:
        cv2.drawContours(close, [c], -1, (0,0,0), -1)

final = 255 - close 
cv2.imshow('removed', removed)
cv2.imshow('thresh', thresh)
cv2.imshow('close', close)
cv2.imshow('final', final)
cv2.waitKey()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...