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
1.6k views
in Technique[技术] by (71.8m points)

opencv - Python Extract number from simple Image

I have the following image

enter image description here

lower = np.array([175, 125, 45], dtype="uint8")
upper = np.array([255, 255, 255], dtype="uint8")

mask = cv2.inRange(image, lower, upper)
img = cv2.bitwise_and(image, image, mask=mask)

plt.figure()
plt.imshow(img)
plt.axis('off')
plt.show()

enter image description here

now if I try to transform into grayscale like this:

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

I get that:

enter image description here

And I would like to extract the number on it.

The suggestion:

gray = 255 - gray
emp = np.full_like(gray, 255)
emp -= gray
emp[emp==0] = 255
emp[emp<100] = 0
gauss = cv2.GaussianBlur(emp, (3,3), 1)
gauss[gauss<220] = 0
plt.imshow(gauss)

gives the image:

enter image description here

Then using pytesseract on any of the images:

data = pytesseract.image_to_string(img, config='outputbase digits')

gives:

'x0c'

Another suggested solution is:

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
thr = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV)[1]
txt = pytesseract.image_to_string(thr)
plt.imshow(thr)

enter image description here

And this gives

'x0c'

Not very satisfying... Anyone has a better solution please?

Thanks!

question from:https://stackoverflow.com/questions/65832561/python-extract-number-from-simple-image

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

1 Reply

0 votes
by (71.8m points)

I have a two step solution


When you apply thresholding to the image:

enter image description here

Thresholding is a simplest method of displaying the features of the image.

Now from the output image, when we read:

txt = image_to_string(thr, config="--psm 7")
print(txt)

Result will be:

| 1,625 |

Now why do we set page-segmentation-mode (psm) mode to the 7?

Well, treating image as a single text line will give the accurate result.

But we have to modify the result. Since the current result is | 1,625 |

We should remove the |

print("".join([t for t in txt if t != '|']))

Result:

1,625

Code:


import cv2
from pytesseract import image_to_string

img = cv2.imread("LZ3vi.png")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thr = cv2.threshold(gry, 0, 255,
                    cv2.THRESH_BINARY_INV)[1]
txt = image_to_string(thr, config="--psm 7")
print("".join([t for t in txt if t != '|']).strip())

Update


how do you get this clean black and white image from my original image?

Using 3-steps

    1. Reading the image using opencv's imread function
    • img = cv2.imread("LZ3vi.png")
      
    • Now we read the image in BGR fashion. (Not RGB)

    1. Convert the image to the graysclae
    • gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
      
    • Result will be:

      • enter image description here
    1. Apply threshold
    • thr = cv2.threshold(gry, 0, 255, cv2.THRESH_BINARY_INV)[1]
      
    • Result will be:

      • enter image description here

Now if you are wondering about thresholding. Read the simple-threhsolding

All my filters, grayscale... get weird colored images

The reason is, when you are displaying the image using pyplot, you need to set color-map (cmap) to gray

plt.imshow(img, cmap='gray')

You can read the other types here


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

...