Pytesseract not giving expected output











up vote
1
down vote

favorite












I'm new to pyhton and I'm making a number plate recognition system using haar cascade. My code works fine to detect the number plate and make contours but pytesseract ocr fails to recognise the characters and gives strange results. Please help.



The detected plate using haar cascades



contours made on the detected region



This is the output



import cv2
import numpy as np
import pytesseract

plate_cascade = cv2.CascadeClassifier('C:/Users/Jai/Desktop/Test/haarcascade_plate.xml')

img = cv2.imread('C:/Users/Jai/Desktop/Test/images/NumberPlates/IMG_20181029_194221.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')
cv2.imshow('gray', gray)

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(255,0,0),5)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

roiUGray = cv2.bitwise_not(roiGray)
cv2.imshow('img', img)
cv2.imshow('roi_gray', roiUGray)

ret, thresh = cv2.threshold(roiUGray, 127, 255,0)
cv2.imshow("img", img)
height, width = thresh.shape
newImage = np.zeros((height, width, 3), np.uint8)
newImage[:, :] = (0,0,0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

num = 0
area = 0

for j in range(len(contours)):
if hierarchy[0][j][3] != -1:
area = area + cv2.contourArea(contours[j])
num += 1

if num != 0:
avgArea = float(area)/float(num)

for j in range(len(contours)):
if hierarchy[0][j][3] != -1 and cv2.contourArea(contours[j]) > 0.2*avgArea:
cv2.drawContours(newImage, contours[j], -1, (255,255,255), 1)

blur = cv2.GaussianBlur(newImage, (1, 1), 0)
cv2.imshow("roi", blur)

ocr_result = pytesseract.image_to_string(blur, lang='eng')
print(ocr_result)

cv2.waitKey(0)
cv2.destroyAllWindows()









share|improve this question


















  • 1




    My suggestion is to crop the contour selected place of Image and give directly to Tesseract , you can get your required output
    – Naga Kiran
    Nov 11 at 8:49










  • Could you upload the original image so I can test? Thanks.
    – qr7NmUTjF6vbA4n8V3J9
    Nov 11 at 12:12










  • I've already uploaded the original image
    – Jai Ahuja
    Nov 12 at 20:38















up vote
1
down vote

favorite












I'm new to pyhton and I'm making a number plate recognition system using haar cascade. My code works fine to detect the number plate and make contours but pytesseract ocr fails to recognise the characters and gives strange results. Please help.



The detected plate using haar cascades



contours made on the detected region



This is the output



import cv2
import numpy as np
import pytesseract

plate_cascade = cv2.CascadeClassifier('C:/Users/Jai/Desktop/Test/haarcascade_plate.xml')

img = cv2.imread('C:/Users/Jai/Desktop/Test/images/NumberPlates/IMG_20181029_194221.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')
cv2.imshow('gray', gray)

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(255,0,0),5)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

roiUGray = cv2.bitwise_not(roiGray)
cv2.imshow('img', img)
cv2.imshow('roi_gray', roiUGray)

ret, thresh = cv2.threshold(roiUGray, 127, 255,0)
cv2.imshow("img", img)
height, width = thresh.shape
newImage = np.zeros((height, width, 3), np.uint8)
newImage[:, :] = (0,0,0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

num = 0
area = 0

for j in range(len(contours)):
if hierarchy[0][j][3] != -1:
area = area + cv2.contourArea(contours[j])
num += 1

if num != 0:
avgArea = float(area)/float(num)

for j in range(len(contours)):
if hierarchy[0][j][3] != -1 and cv2.contourArea(contours[j]) > 0.2*avgArea:
cv2.drawContours(newImage, contours[j], -1, (255,255,255), 1)

blur = cv2.GaussianBlur(newImage, (1, 1), 0)
cv2.imshow("roi", blur)

ocr_result = pytesseract.image_to_string(blur, lang='eng')
print(ocr_result)

cv2.waitKey(0)
cv2.destroyAllWindows()









share|improve this question


















  • 1




    My suggestion is to crop the contour selected place of Image and give directly to Tesseract , you can get your required output
    – Naga Kiran
    Nov 11 at 8:49










  • Could you upload the original image so I can test? Thanks.
    – qr7NmUTjF6vbA4n8V3J9
    Nov 11 at 12:12










  • I've already uploaded the original image
    – Jai Ahuja
    Nov 12 at 20:38













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I'm new to pyhton and I'm making a number plate recognition system using haar cascade. My code works fine to detect the number plate and make contours but pytesseract ocr fails to recognise the characters and gives strange results. Please help.



The detected plate using haar cascades



contours made on the detected region



This is the output



import cv2
import numpy as np
import pytesseract

plate_cascade = cv2.CascadeClassifier('C:/Users/Jai/Desktop/Test/haarcascade_plate.xml')

img = cv2.imread('C:/Users/Jai/Desktop/Test/images/NumberPlates/IMG_20181029_194221.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')
cv2.imshow('gray', gray)

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(255,0,0),5)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

roiUGray = cv2.bitwise_not(roiGray)
cv2.imshow('img', img)
cv2.imshow('roi_gray', roiUGray)

ret, thresh = cv2.threshold(roiUGray, 127, 255,0)
cv2.imshow("img", img)
height, width = thresh.shape
newImage = np.zeros((height, width, 3), np.uint8)
newImage[:, :] = (0,0,0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

num = 0
area = 0

for j in range(len(contours)):
if hierarchy[0][j][3] != -1:
area = area + cv2.contourArea(contours[j])
num += 1

if num != 0:
avgArea = float(area)/float(num)

for j in range(len(contours)):
if hierarchy[0][j][3] != -1 and cv2.contourArea(contours[j]) > 0.2*avgArea:
cv2.drawContours(newImage, contours[j], -1, (255,255,255), 1)

blur = cv2.GaussianBlur(newImage, (1, 1), 0)
cv2.imshow("roi", blur)

ocr_result = pytesseract.image_to_string(blur, lang='eng')
print(ocr_result)

cv2.waitKey(0)
cv2.destroyAllWindows()









share|improve this question













I'm new to pyhton and I'm making a number plate recognition system using haar cascade. My code works fine to detect the number plate and make contours but pytesseract ocr fails to recognise the characters and gives strange results. Please help.



The detected plate using haar cascades



contours made on the detected region



This is the output



import cv2
import numpy as np
import pytesseract

plate_cascade = cv2.CascadeClassifier('C:/Users/Jai/Desktop/Test/haarcascade_plate.xml')

img = cv2.imread('C:/Users/Jai/Desktop/Test/images/NumberPlates/IMG_20181029_194221.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')
cv2.imshow('gray', gray)

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(255,0,0),5)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

roiUGray = cv2.bitwise_not(roiGray)
cv2.imshow('img', img)
cv2.imshow('roi_gray', roiUGray)

ret, thresh = cv2.threshold(roiUGray, 127, 255,0)
cv2.imshow("img", img)
height, width = thresh.shape
newImage = np.zeros((height, width, 3), np.uint8)
newImage[:, :] = (0,0,0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

num = 0
area = 0

for j in range(len(contours)):
if hierarchy[0][j][3] != -1:
area = area + cv2.contourArea(contours[j])
num += 1

if num != 0:
avgArea = float(area)/float(num)

for j in range(len(contours)):
if hierarchy[0][j][3] != -1 and cv2.contourArea(contours[j]) > 0.2*avgArea:
cv2.drawContours(newImage, contours[j], -1, (255,255,255), 1)

blur = cv2.GaussianBlur(newImage, (1, 1), 0)
cv2.imshow("roi", blur)

ocr_result = pytesseract.image_to_string(blur, lang='eng')
print(ocr_result)

cv2.waitKey(0)
cv2.destroyAllWindows()






python python-3.x opencv pytesseract






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 11 at 8:08









Jai Ahuja

82




82








  • 1




    My suggestion is to crop the contour selected place of Image and give directly to Tesseract , you can get your required output
    – Naga Kiran
    Nov 11 at 8:49










  • Could you upload the original image so I can test? Thanks.
    – qr7NmUTjF6vbA4n8V3J9
    Nov 11 at 12:12










  • I've already uploaded the original image
    – Jai Ahuja
    Nov 12 at 20:38














  • 1




    My suggestion is to crop the contour selected place of Image and give directly to Tesseract , you can get your required output
    – Naga Kiran
    Nov 11 at 8:49










  • Could you upload the original image so I can test? Thanks.
    – qr7NmUTjF6vbA4n8V3J9
    Nov 11 at 12:12










  • I've already uploaded the original image
    – Jai Ahuja
    Nov 12 at 20:38








1




1




My suggestion is to crop the contour selected place of Image and give directly to Tesseract , you can get your required output
– Naga Kiran
Nov 11 at 8:49




My suggestion is to crop the contour selected place of Image and give directly to Tesseract , you can get your required output
– Naga Kiran
Nov 11 at 8:49












Could you upload the original image so I can test? Thanks.
– qr7NmUTjF6vbA4n8V3J9
Nov 11 at 12:12




Could you upload the original image so I can test? Thanks.
– qr7NmUTjF6vbA4n8V3J9
Nov 11 at 12:12












I've already uploaded the original image
– Jai Ahuja
Nov 12 at 20:38




I've already uploaded the original image
– Jai Ahuja
Nov 12 at 20:38












1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










This method uses contour detection to find the area of the number plate, and does a perspective transform on it. It then uses adaptive thresholding to detect the digits and does a medianBlur to get rid of noise that messes up the pytesseract operation.





The blue box is from the original image. The red box is from my number plate recognition haar cascade. The green is the contour detection of the number plate.





Here's the output of the perspective transform. I used the imutils module to do this.





This is the output of the adaptive thresholding and blurring, which I used the skimage module for.



Using this I got the output of:




fUP1ADN7120




And removing all characters that aren't uppercase or a digit gives:




UP1ADN7120




Which is only one character wrong.



This method isn't too bad, but you could get even better using another method. If this didn't work for you, then you could create a CNN.



Here's the code:



import cv2
import numpy as np
import pytesseract
import imutils.perspective
from skimage.filters import threshold_local

plate_cascade = cv2.CascadeClassifier('/usr/local/lib/python3.5/dist-packages/cv2/data/haarcascade_russian_plate_number.xml')

img = cv2.imread('GNA0d.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(0,0,255),2)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

blur = cv2.GaussianBlur(roiGray, (5, 5), 0)
edges = cv2.Canny(blur, 75, 200)

contours = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5] #sort the contours, only getting the biggest to improve speed

for contour in contours:
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)

#find contours with 4 edges
if len(approx) == 4:
screenCnt = approx
break

orig = roiImg.copy()
cv2.drawContours(roiImg, [screenCnt], -1, (0, 255, 0), 2)

#do a perspective transform
warped = imutils.perspective.four_point_transform(orig, screenCnt.reshape(4, 2))
graywarp = imutils.perspective.four_point_transform(roiGray, screenCnt.reshape(4, 2))

#threshold using adaptive thresholding
T = threshold_local(graywarp, 11, offset = 10, method = "gaussian")
graywarp = (graywarp > T).astype("uint8") * 255

#do a median blur to remove noise
graywarp = cv2.medianBlur(graywarp, 3)

text = pytesseract.image_to_string(graywarp)
print(text)
print("".join([c for c in text if c.isupper() or c.isdigit()]))


cv2.imshow("warped", warped)
cv2.imshow("graywarp", graywarp)
cv2.imshow('img', img)


cv2.waitKey(0)
cv2.destroyAllWindows()


Quite a bit was taken from pyimagesearch, who explains it better than I ever could.






share|improve this answer























  • Thanks for the help. Really appreciate it. Will try it out for sure.
    – Jai Ahuja
    Nov 12 at 20:38






  • 1




    @JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
    – Dmitrii Z.
    Nov 14 at 15:05











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246894%2fpytesseract-not-giving-expected-output%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










This method uses contour detection to find the area of the number plate, and does a perspective transform on it. It then uses adaptive thresholding to detect the digits and does a medianBlur to get rid of noise that messes up the pytesseract operation.





The blue box is from the original image. The red box is from my number plate recognition haar cascade. The green is the contour detection of the number plate.





Here's the output of the perspective transform. I used the imutils module to do this.





This is the output of the adaptive thresholding and blurring, which I used the skimage module for.



Using this I got the output of:




fUP1ADN7120




And removing all characters that aren't uppercase or a digit gives:




UP1ADN7120




Which is only one character wrong.



This method isn't too bad, but you could get even better using another method. If this didn't work for you, then you could create a CNN.



Here's the code:



import cv2
import numpy as np
import pytesseract
import imutils.perspective
from skimage.filters import threshold_local

plate_cascade = cv2.CascadeClassifier('/usr/local/lib/python3.5/dist-packages/cv2/data/haarcascade_russian_plate_number.xml')

img = cv2.imread('GNA0d.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(0,0,255),2)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

blur = cv2.GaussianBlur(roiGray, (5, 5), 0)
edges = cv2.Canny(blur, 75, 200)

contours = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5] #sort the contours, only getting the biggest to improve speed

for contour in contours:
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)

#find contours with 4 edges
if len(approx) == 4:
screenCnt = approx
break

orig = roiImg.copy()
cv2.drawContours(roiImg, [screenCnt], -1, (0, 255, 0), 2)

#do a perspective transform
warped = imutils.perspective.four_point_transform(orig, screenCnt.reshape(4, 2))
graywarp = imutils.perspective.four_point_transform(roiGray, screenCnt.reshape(4, 2))

#threshold using adaptive thresholding
T = threshold_local(graywarp, 11, offset = 10, method = "gaussian")
graywarp = (graywarp > T).astype("uint8") * 255

#do a median blur to remove noise
graywarp = cv2.medianBlur(graywarp, 3)

text = pytesseract.image_to_string(graywarp)
print(text)
print("".join([c for c in text if c.isupper() or c.isdigit()]))


cv2.imshow("warped", warped)
cv2.imshow("graywarp", graywarp)
cv2.imshow('img', img)


cv2.waitKey(0)
cv2.destroyAllWindows()


Quite a bit was taken from pyimagesearch, who explains it better than I ever could.






share|improve this answer























  • Thanks for the help. Really appreciate it. Will try it out for sure.
    – Jai Ahuja
    Nov 12 at 20:38






  • 1




    @JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
    – Dmitrii Z.
    Nov 14 at 15:05















up vote
2
down vote



accepted










This method uses contour detection to find the area of the number plate, and does a perspective transform on it. It then uses adaptive thresholding to detect the digits and does a medianBlur to get rid of noise that messes up the pytesseract operation.





The blue box is from the original image. The red box is from my number plate recognition haar cascade. The green is the contour detection of the number plate.





Here's the output of the perspective transform. I used the imutils module to do this.





This is the output of the adaptive thresholding and blurring, which I used the skimage module for.



Using this I got the output of:




fUP1ADN7120




And removing all characters that aren't uppercase or a digit gives:




UP1ADN7120




Which is only one character wrong.



This method isn't too bad, but you could get even better using another method. If this didn't work for you, then you could create a CNN.



Here's the code:



import cv2
import numpy as np
import pytesseract
import imutils.perspective
from skimage.filters import threshold_local

plate_cascade = cv2.CascadeClassifier('/usr/local/lib/python3.5/dist-packages/cv2/data/haarcascade_russian_plate_number.xml')

img = cv2.imread('GNA0d.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(0,0,255),2)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

blur = cv2.GaussianBlur(roiGray, (5, 5), 0)
edges = cv2.Canny(blur, 75, 200)

contours = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5] #sort the contours, only getting the biggest to improve speed

for contour in contours:
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)

#find contours with 4 edges
if len(approx) == 4:
screenCnt = approx
break

orig = roiImg.copy()
cv2.drawContours(roiImg, [screenCnt], -1, (0, 255, 0), 2)

#do a perspective transform
warped = imutils.perspective.four_point_transform(orig, screenCnt.reshape(4, 2))
graywarp = imutils.perspective.four_point_transform(roiGray, screenCnt.reshape(4, 2))

#threshold using adaptive thresholding
T = threshold_local(graywarp, 11, offset = 10, method = "gaussian")
graywarp = (graywarp > T).astype("uint8") * 255

#do a median blur to remove noise
graywarp = cv2.medianBlur(graywarp, 3)

text = pytesseract.image_to_string(graywarp)
print(text)
print("".join([c for c in text if c.isupper() or c.isdigit()]))


cv2.imshow("warped", warped)
cv2.imshow("graywarp", graywarp)
cv2.imshow('img', img)


cv2.waitKey(0)
cv2.destroyAllWindows()


Quite a bit was taken from pyimagesearch, who explains it better than I ever could.






share|improve this answer























  • Thanks for the help. Really appreciate it. Will try it out for sure.
    – Jai Ahuja
    Nov 12 at 20:38






  • 1




    @JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
    – Dmitrii Z.
    Nov 14 at 15:05













up vote
2
down vote



accepted







up vote
2
down vote



accepted






This method uses contour detection to find the area of the number plate, and does a perspective transform on it. It then uses adaptive thresholding to detect the digits and does a medianBlur to get rid of noise that messes up the pytesseract operation.





The blue box is from the original image. The red box is from my number plate recognition haar cascade. The green is the contour detection of the number plate.





Here's the output of the perspective transform. I used the imutils module to do this.





This is the output of the adaptive thresholding and blurring, which I used the skimage module for.



Using this I got the output of:




fUP1ADN7120




And removing all characters that aren't uppercase or a digit gives:




UP1ADN7120




Which is only one character wrong.



This method isn't too bad, but you could get even better using another method. If this didn't work for you, then you could create a CNN.



Here's the code:



import cv2
import numpy as np
import pytesseract
import imutils.perspective
from skimage.filters import threshold_local

plate_cascade = cv2.CascadeClassifier('/usr/local/lib/python3.5/dist-packages/cv2/data/haarcascade_russian_plate_number.xml')

img = cv2.imread('GNA0d.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(0,0,255),2)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

blur = cv2.GaussianBlur(roiGray, (5, 5), 0)
edges = cv2.Canny(blur, 75, 200)

contours = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5] #sort the contours, only getting the biggest to improve speed

for contour in contours:
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)

#find contours with 4 edges
if len(approx) == 4:
screenCnt = approx
break

orig = roiImg.copy()
cv2.drawContours(roiImg, [screenCnt], -1, (0, 255, 0), 2)

#do a perspective transform
warped = imutils.perspective.four_point_transform(orig, screenCnt.reshape(4, 2))
graywarp = imutils.perspective.four_point_transform(roiGray, screenCnt.reshape(4, 2))

#threshold using adaptive thresholding
T = threshold_local(graywarp, 11, offset = 10, method = "gaussian")
graywarp = (graywarp > T).astype("uint8") * 255

#do a median blur to remove noise
graywarp = cv2.medianBlur(graywarp, 3)

text = pytesseract.image_to_string(graywarp)
print(text)
print("".join([c for c in text if c.isupper() or c.isdigit()]))


cv2.imshow("warped", warped)
cv2.imshow("graywarp", graywarp)
cv2.imshow('img', img)


cv2.waitKey(0)
cv2.destroyAllWindows()


Quite a bit was taken from pyimagesearch, who explains it better than I ever could.






share|improve this answer














This method uses contour detection to find the area of the number plate, and does a perspective transform on it. It then uses adaptive thresholding to detect the digits and does a medianBlur to get rid of noise that messes up the pytesseract operation.





The blue box is from the original image. The red box is from my number plate recognition haar cascade. The green is the contour detection of the number plate.





Here's the output of the perspective transform. I used the imutils module to do this.





This is the output of the adaptive thresholding and blurring, which I used the skimage module for.



Using this I got the output of:




fUP1ADN7120




And removing all characters that aren't uppercase or a digit gives:




UP1ADN7120




Which is only one character wrong.



This method isn't too bad, but you could get even better using another method. If this didn't work for you, then you could create a CNN.



Here's the code:



import cv2
import numpy as np
import pytesseract
import imutils.perspective
from skimage.filters import threshold_local

plate_cascade = cv2.CascadeClassifier('/usr/local/lib/python3.5/dist-packages/cv2/data/haarcascade_russian_plate_number.xml')

img = cv2.imread('GNA0d.jpg', cv2.IMREAD_COLOR)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.array(gray, dtype='uint8')

plates = plate_cascade.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in plates:
cv2.rectangle(img, (x,y), (x+w,y+h),(0,0,255),2)
roiGray = gray[y:y+h, x:x+w]
roiImg = img[y:y+h, x:x+w]

blur = cv2.GaussianBlur(roiGray, (5, 5), 0)
edges = cv2.Canny(blur, 75, 200)

contours = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5] #sort the contours, only getting the biggest to improve speed

for contour in contours:
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)

#find contours with 4 edges
if len(approx) == 4:
screenCnt = approx
break

orig = roiImg.copy()
cv2.drawContours(roiImg, [screenCnt], -1, (0, 255, 0), 2)

#do a perspective transform
warped = imutils.perspective.four_point_transform(orig, screenCnt.reshape(4, 2))
graywarp = imutils.perspective.four_point_transform(roiGray, screenCnt.reshape(4, 2))

#threshold using adaptive thresholding
T = threshold_local(graywarp, 11, offset = 10, method = "gaussian")
graywarp = (graywarp > T).astype("uint8") * 255

#do a median blur to remove noise
graywarp = cv2.medianBlur(graywarp, 3)

text = pytesseract.image_to_string(graywarp)
print(text)
print("".join([c for c in text if c.isupper() or c.isdigit()]))


cv2.imshow("warped", warped)
cv2.imshow("graywarp", graywarp)
cv2.imshow('img', img)


cv2.waitKey(0)
cv2.destroyAllWindows()


Quite a bit was taken from pyimagesearch, who explains it better than I ever could.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 20:45

























answered Nov 11 at 13:12









qr7NmUTjF6vbA4n8V3J9

1686




1686












  • Thanks for the help. Really appreciate it. Will try it out for sure.
    – Jai Ahuja
    Nov 12 at 20:38






  • 1




    @JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
    – Dmitrii Z.
    Nov 14 at 15:05


















  • Thanks for the help. Really appreciate it. Will try it out for sure.
    – Jai Ahuja
    Nov 12 at 20:38






  • 1




    @JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
    – Dmitrii Z.
    Nov 14 at 15:05
















Thanks for the help. Really appreciate it. Will try it out for sure.
– Jai Ahuja
Nov 12 at 20:38




Thanks for the help. Really appreciate it. Will try it out for sure.
– Jai Ahuja
Nov 12 at 20:38




1




1




@JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
– Dmitrii Z.
Nov 14 at 15:05




@JaiAhuja if this answer solves your original issue - please consider marking it as an accepted answer.
– Dmitrii Z.
Nov 14 at 15:05


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246894%2fpytesseract-not-giving-expected-output%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

The Sandy Post

Danny Elfman

Pages that link to "Head v. Amoskeag Manufacturing Co."