Unable to read image text with python tesseract and OpenCV

Question:

I am trying read text from this

this image

using Python with OpenCV. However, it is not able to read it.

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img=cv.imread(file_path,0)

img = cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)

th2 =cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,
    cv.THRESH_BINARY,11,2)

th3 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv.THRESH_BINARY,11,2)

titles = ['Original Image', 'Global Thresholding (v = 127)',
    'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']

images = [img, th1, th2, th3]

for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

anyway to do this?

Asked By: Optimus

||

Answers:

Instead of working on the grayscale image, working on saturation channel of the HSV color space makes the subsequent steps easier.

img = cv2.imread(image_path_to_captcha)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
s_component = hsv[:,:,1]

s_component
enter image description here

Next, apply a Gaussian blur of appropriate kernel size and sigma value, and later threshold.

blur = cv2.GaussianBlur(s_component,(7,7), 7)
ret,th3 = cv2.threshold(blur,127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

th3
enter image description here

Next, finding contours in the image above and preserving those above a certain area threshold in the black image variable which will be used as mask later on.

contours, hierarchy = cv2.findContours(th3, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
black = np.zeros((img.shape[0], img.shape[1]), np.uint8)

for contour in contours:
    if cv2.contourArea(contour) >600 :
        cv2.drawContours(black, [contour], 0, 255, -1)

black
enter image description here

Using the black image variable as mask over the threshold image

res = cv2.bitwise_and(th3, th3, mask = black)   

res
enter image description here

Finally, applying morphological thinning to the above result

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
erode = cv2.erode(res, kernel, iterations=1)

erode
enter image description here

The end result is not what you expect. You can try experimenting different morphology operations prior to drawing contours as well.

EDIT

You can perform distance transform on the above image and use the result:

dist = cv2.distanceTransform(res, cv2.DIST_L2, 3)
dst = cv2.normalize(dist, dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

dst
enter image description here

Answered By: Jeru Luke