简体   繁体   中英

OpenCV :Text Processing and Noise Removal

I would like to remove the background of an image that contains text to make it text on white background.

sample of image
在此处输入图片说明

I have tried till now to get HSV of an image and upper and lower boundaries but I can't find upper and lower boundaries that can remove all the background effect

Code used till now :

import cv2
import numpy as np


# Take each frame
filename = 'img2.png'

img = cv2.imread(filename, 1)

# Convert BGR to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
# Threshold the HSV image to get only blue colors
image_final = cv2.inRange(hsv, lower_blue, upper_blue)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(img,img, mask= mask)
cv2.imshow('frame',img)
cv2.imwrite('mask.png',image_final)


cv2.waitKey(0)

Is there a better way to it or do I have to combine multiple lower and upper boundaries to reach my goal?

You could read the image as grayscale and set a treshold:

import cv2

img = cv2.imread('img2.png', 0)     # 0 means grayscale
new_img = (img >= 230)*255          # 230 is the threshold, change as desired
cv2.imwrite('mask.png',new_img)

This transforms the left pic into the right:

原版的 输出量

Since your pictures all have pure white letters, you can probably just choose a constant threshold that's quite high (as 0 would be black and 255 white), eg 230.

EDIT

@Ishara Madhawa had a very nice idea of using kernels to get rid of the central stripes. However, if you use cv2.morphologyEx instead, you do not change the thickness of the letters:

import cv2

img = cv2.imread('img2.png', 0)
new_img = ((img >= 230)*255).astype('uint8')
cv2.imwrite('mask.png',255-new_img)    # 255-... to get black on white

kernel = np.ones((5, 1), np.uint8)    
new_img2 = cv2.morphologyEx(new_img, cv2.MORPH_CLOSE, kernel)
cv2.imwrite('mask2.png',255-new_img2)

没有内核 带内核

This solution will solve your problem.

This is the full code for the solution:

import cv2
import numpy as np
image = cv2.imread('input.png',0)

retval, thresh_gray = cv2.threshold(image, thresh=200, maxval=255,type=cv2.THRESH_BINARY_INV)

cv2.bitwise_not(thresh_gray,thresh_gray)

kernel = np.ones((5, 1), np.uint8)
joined = cv2.dilate(thresh_gray, kernel, iterations=1)
cv2.imshow('joined', joined)
cv2.waitKey(0)

First you should read the image as grayscale.

image = cv2.imread('input.png',0)

output:

After that you should set a threshold value in order to get rid of background noise. In this case I have set a manual threshold (200) to get the most optimized result.

retval, thresh_gray = cv2.threshold(image, thresh=200, maxval=255,type=cv2.THRESH_BINARY_INV)

output:

Then, after performing bitwise_not (to swap black and white) You should use a 5 x 1 kernel to join separated characters from middle. Two horizontal lines in the middle of the character will disappear.

cv2.bitwise_not(thresh_gray,thresh_gray)
kernel = np.ones((5, 1), np.uint8)
joined = cv2.dilate(thresh_gray, kernel, iterations=1)

output:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM