Issue
I have multiple image with different background,
i need to ignore background and extract Number from my image. ex:
after test, i have this result :
because of background color, it's very difficult to extract text..
i'm using this code:
image = cv2.imread('AA.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 165, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Invert image and perform morphological operations
inverted = 255 - thresh
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,3))
close = cv2.morphologyEx(inverted, cv2.MORPH_CLOSE, kernel, iterations=1)
# Find contours and filter using aspect ratio and area
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)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.01 * peri, True)
x,y,w,h = cv2.boundingRect(approx)
aspect_ratio = w / float(h)
if (aspect_ratio >= 2.5 or area < 75):
cv2.drawContours(thresh, [c], -1, (255,255,255), -1)
# Blur and perform text extraction
thresh = cv2.GaussianBlur(thresh, (3,3), 0)
data = pytesseract.image_to_string(thresh, lang='eng',config='tessedit_char_whitelist=0123456789 --psm 6')
print(data)
cv2.imshow('close', close)
cv2.imshow('thresh', thresh)
cv2.waitKey()
How i can extract number from this image with accuracy even if background color change?
Edit result after modification:
Solution
Your thresholding is your problem. Here is how I would process the image in Python/OpenCV before doing OCR.
I simply threshold at 165 to make the letters white and the background black. Then filter contours on area to remove the small extraneous white regions. Then invert the results so that you have black letters on white background.
Input:
import cv2
import numpy as np
# load image as HSV and select saturation
img = cv2.imread("numbers.png")
hh, ww, cc = img.shape
# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold the grayscale image
ret, thresh = cv2.threshold(gray,165,255,0)
# create black image to hold results
results = np.zeros((hh,ww))
# find contours
cntrs = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
# Contour filtering and copy contour interior to new black image.
for c in cntrs:
area = cv2.contourArea(c)
if area > 1000:
x,y,w,h = cv2.boundingRect(c)
results[y:y+h,x:x+w] = thresh[y:y+h,x:x+w]
# invert the results image so that have black letters on white background
results = (255 - results)
# write results to disk
cv2.imwrite("numbers_extracted.png", results)
cv2.imshow("THRESH", thresh)
cv2.imshow("RESULTS", results)
cv2.waitKey(0)
cv2.destroyAllWindows()
Thresholded Image Before Contour Filtering:
Results after contour filtering and inversion:
P.S. cv2.inRange() may be an alternative to cv2.threshold.
And of course this solution may be limited to this one image, since other images may need different values for the threshold and area limits.
Answered By - fmw42
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.