Search code examples
opencvtesseractpython-tesseract

Tesseract fails to parse text from image


I'm completely new to opencv and tesseract. I spent all day trying to make code that would parse game duration from images like that: original image (game duration is in the top left corner)

I came to code that manages to recognize the duration sometimes (about 40% of all cases). Here it is:

try:
    from PIL import Image
except ImportError:
    import Image
import os
import cv2
import pytesseract
import re
import json

def non_digit_split(s):
    return filter(None, re.split(r'(\d+)', s))

def time_to_sec(min, sec):
    return (int(min) * 60 + int(sec)).__str__()

def process_img(image_url):
    img = cv2.resize(cv2.imread('./images/' + image_url), None, fx=5, fy=5, interpolation=cv2.INTER_CUBIC)
    str = pytesseract.image_to_string(img)

    if "WIN " in str:
        time = list(non_digit_split(str.split("WIN ",1)[1][0:6].strip()))
        str = time_to_sec(time[0], time[2])
    else:
        str = 'Not recognized'
    return str

res = {}
img_list = os.listdir('./images')
print(img_list)

for i in img_list:
    res[i] = process_img(i)

with open('output.txt', 'w') as file:
     file.write(json.dumps(res))

Don't even ask how I came to resizing image, but it helped a little. I also tried to crop image first like that: cropped image but tesseract couldn't find any text here.

I'm sure that the issue I'm trying to solve is pretty easy. Can you please point me the right direction? How should I preprocess it so tesseract will parse it right?


Solution

  • Thanks to @DmitriiZ comment I managed to produce working piece of code. I made a preprocessor that outputs something like that: Preprocessed image Tesseract handles it just fine.

    Here is the full code:

    try:
        from PIL import Image
    except ImportError:
        import Image
    import os
    import pytesseract
    import json
    
    def is_dark(image):
        pixels = image.getdata()
        black_thresh = 100
        nblack = 0
        for pixel in pixels:
            if (sum(pixel) / 3) < black_thresh:
                nblack += 1
        n = len(pixels)
    
        if (nblack / float(n)) > 0.5:
            return True
        else:
            return False
    
    def preprocess(img):
        basewidth = 500
        wpercent = (basewidth/float(img.size[0]))
        hsize = int((float(img.size[1])*float(wpercent)))
    
        #Enlarging image
        img = img.resize((basewidth,hsize), Image.ANTIALIAS)
    
        #Converting image to black and white
        img = img.convert("1", dither=Image.NONE)
        return img
    
    def process_img(image_url):
        img = Image.open('./images/' + image_url)
    
        #Area we need to crop can be found in one of two different areas,
        #depending on which team won. You can replace that block and is_dark()
        #function by just img.crop().
        top_area = (287, 15, 332, 32)
        crop = img.crop(top_area)
        if is_dark(crop):
            bot_area = (287, 373, 332, 390)
            crop = img.crop(bot_area)
    
        img = preprocess(crop)
    
        str = pytesseract.image_to_string(img)
    
        return str
    
    res = {}
    img_list = os.listdir('./images')
    print(img_list)
    
    for i in img_list:
        res[i] = process_img(i)
    
    with open('output.txt', 'w') as file:
         file.write(json.dumps(res))