Skip to content

Commit ef0ef21

Browse files
committed
1
1 parent e2a9bb2 commit ef0ef21

6 files changed

+134
-90
lines changed

DetectChars.py

+39-33
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import random
77

88
import Main
9+
import Preprocess
910
import PossibleChar
1011

1112
# module level variables ##########################################################################
@@ -85,7 +86,7 @@ def detectCharsInPlates(listOfPossiblePlates):
8586
# at this point we can be sure the list of possible plates has at least one plate
8687

8788
for possiblePlate in listOfPossiblePlates:
88-
preprocess(possiblePlate.imgPlate, possiblePlate.imgGrayscale, possiblePlate.imgThresh)
89+
possiblePlate.imgGrayscale, possiblePlate.imgThresh = Preprocess.preprocess(possiblePlate.imgPlate)
8990

9091
if Main.showSteps == True:
9192
cv2.imshow("5a", possiblePlate.imgPlate)
@@ -94,18 +95,19 @@ def detectCharsInPlates(listOfPossiblePlates):
9495
# end if
9596

9697
# increase size of plate image for easier viewing and char detection
97-
cv2.resize(possiblePlate.imgThresh, 0, possiblePlate.imgThresh, 1.6, 1.6)
98+
possiblePlate.imgThresh = cv2.resize(possiblePlate.imgThresh, (0, 0), fx = 1.6, fy = 1.6)
9899

99100
# threshold image to only black or white (eliminate grayscale)
100-
possiblePlate.imgThresh = cv2.threshold(possiblePlate.imgThresh, 0.0, 255.0, CV_THRESH_BINARY | CV_THRESH_OTSU)
101+
thresholdValue, possiblePlate.imgThresh = cv2.threshold(possiblePlate.imgThresh, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
101102

102103
if Main.showSteps == True:
103104
cv2.imshow("5d", possiblePlate.imgThresh)
104105
# end if
105106

106-
listOfPossibleCharsInPlate = findPossibleCharsInPlate(possiblePlate.imgGrayscale, possiblePlate.imgThresh);
107+
listOfPossibleCharsInPlate = findPossibleCharsInPlate(possiblePlate.imgGrayscale, possiblePlate.imgThresh)
107108

108109
if Main.showSteps == True:
110+
height, width, numChannels = possiblePlate.imgPlate.shape
109111
imgContours = np.zeros((height, width, 3), np.uint8)
110112
del contours[:] # clear the contours list
111113

@@ -118,7 +120,7 @@ def detectCharsInPlates(listOfPossiblePlates):
118120
cv2.imshow("6", imgContours)
119121
# end if
120122

121-
listOfListsOfMatchingCharsInPlate = findListOfListsOfMatchingChars(vectorOfPossibleCharsInPlate)
123+
listOfListsOfMatchingCharsInPlate = findListOfListsOfMatchingChars(listOfPossibleCharsInPlate)
122124

123125
if Main.showSteps == True:
124126
imgContours = np.zeros((height, width, 3), np.uint8)
@@ -140,7 +142,7 @@ def detectCharsInPlates(listOfPossiblePlates):
140142
if (len(listOfListsOfMatchingCharsInPlate) == 0): # if no groups of matching chars were found in the plate
141143

142144
if Main.showSteps == True:
143-
print "chars found in plate number " + str(intPlateCounter) + " = (none), click on any image and press a key to continue . . .\n"
145+
print "chars found in plate number " + str(intPlateCounter) + " = (none), click on any image and press a key to continue . . ."
144146
intPlateCounter = intPlateCounter + 1
145147
cv2.destroyWindow("8")
146148
cv2.destroyWindow("9")
@@ -152,9 +154,9 @@ def detectCharsInPlates(listOfPossiblePlates):
152154
continue # go back to top of for loop
153155
# end if
154156

155-
for listOfMatchingChars in listOfListsOfMatchingCharsInPlate:
156-
listOfMatchingChars.sort(key = lambda matchingChar: matchingChar.intCenterX)
157-
listOfMatchingChars = removeInnerOverlappingChars(listOfMatchingChars)
157+
for listOfMatchingChars in listOfListsOfMatchingCharsInPlate: # within each list of matching chars
158+
listOfMatchingChars.sort(key = lambda matchingChar: matchingChar.intCenterX) # sort chars from left to right
159+
listOfMatchingChars = removeInnerOverlappingChars(listOfMatchingChars) # and remove inner overlapping chars
158160
# end for
159161

160162
if Main.showSteps == True:
@@ -188,7 +190,7 @@ def detectCharsInPlates(listOfPossiblePlates):
188190
# end if
189191
# end for
190192

191-
longestListOfMatchingCharsInPlate = listOfListOfMatchingCharsInPlate[intIndexOfLongestListOfChars]
193+
longestListOfMatchingCharsInPlate = listOfListsOfMatchingCharsInPlate[intIndexOfLongestListOfChars]
192194

193195
if Main.showSteps == True:
194196
imgContours = np.zeros((height, width, 3), np.uint8)
@@ -206,7 +208,7 @@ def detectCharsInPlates(listOfPossiblePlates):
206208
possiblePlate.strChars = recognizeCharsInPlate(possiblePlate.imgThresh, longestListOfMatchingCharsInPlate)
207209

208210
if Main.showSteps == True:
209-
print "chars found in plate number " + str(intPlateCounter) + " = " + possiblePlate.strChars + ", click on any image and press a key to continue . . .\n"
211+
print "chars found in plate number " + str(intPlateCounter) + " = " + possiblePlate.strChars + ", click on any image and press a key to continue . . ."
210212
intPlateCounter = intPlateCounter + 1
211213
cv2.waitKey(0)
212214
# end if
@@ -227,9 +229,9 @@ def findPossibleCharsInPlate(imgGrayscale, imgThresh):
227229

228230
contours = []
229231

230-
imgThreshCopy = imgThresh.clone()
232+
imgThreshCopy = imgThresh.copy()
231233

232-
cv2.findContours(imgThreshCopy, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE)
234+
imgContours, contours, npaHierarchy = cv2.findContours(imgThreshCopy, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
233235

234236
for contour in contours:
235237
possibleChar = PossibleChar.PossibleChar(contour)
@@ -273,7 +275,7 @@ def findListOfListsOfMatchingChars(listOfPossibleChars):
273275

274276
listOfPossibleCharsWithCurrentMatchesRemoved = list(set(listOfPossibleChars) - set(listOfMatchingChars))
275277

276-
recursiveListOfListsOfMatchingChars = findListOfListsOfMatchingChars(vectorOfPossibleCharsWithCurrentMatchesRemoved)
278+
recursiveListOfListsOfMatchingChars = findListOfListsOfMatchingChars(listOfPossibleCharsWithCurrentMatchesRemoved)
277279

278280
for recursiveListOfMatchingChars in recursiveListOfListsOfMatchingChars:
279281
listOfListsOfMatchingChars.append(recursiveListOfMatchingChars)
@@ -299,16 +301,17 @@ def findListOfMatchingChars(possibleChar, listOfChars):
299301

300302
fltAngleBetweenChars = angleBetweenChars(possibleChar, possibleMatchingChar)
301303

302-
fltChangeInArea = abs(possibleMatchingChar.intRectArea - possibleChar.intRectArea) / possibleChar.intRectArea
304+
fltChangeInArea = float(abs(possibleMatchingChar.intBoundingRectArea - possibleChar.intBoundingRectArea)) / float(possibleChar.intBoundingRectArea)
303305

304-
dblChangeInWidth = abs(possibleMatchingChar.boundingRect.Width - possibleChar.boundingRect.Width) / possibleChar.boundingRect.Width
305-
dblChangeInHeight = abs(possibleMatchingChar.boundingRect.Height - possibleChar.boundingRect.Height) / possibleChar.boundingRect.Height
306+
fltChangeInWidth = float(abs(possibleMatchingChar.intBoundingRectWidth - possibleChar.intBoundingRectWidth)) / float(possibleChar.intBoundingRectWidth)
307+
fltChangeInHeight = float(abs(possibleMatchingChar.intBoundingRectHeight - possibleChar.intBoundingRectHeight)) / float(possibleChar.intBoundingRectHeight)
308+
309+
if (fltDistanceBetweenChars < (possibleChar.fltDiagonalSize * MAX_DIAG_SIZE_MULTIPLE_AWAY) and
310+
fltAngleBetweenChars < MAX_ANGLE_BETWEEN_CHARS and
311+
fltChangeInArea < MAX_CHANGE_IN_AREA and
312+
fltChangeInWidth < MAX_CHANGE_IN_WIDTH and
313+
fltChangeInHeight < MAX_CHANGE_IN_HEIGHT):
306314

307-
if (dblDistanceBetweenChars < (possibleChar.dblDiagonalSize * MAX_DIAG_SIZE_MULTIPLE_AWAY) and
308-
dblAngleBetweenChars < MAX_ANGLE_BETWEEN_CHARS and
309-
dblChangeInArea < MAX_CHANGE_IN_AREA and
310-
dblChangeInWidth < MAX_CHANGE_IN_WIDTH and
311-
dblChangeInHeight < MAX_CHANGE_IN_HEIGHT):
312315
listOfMatchingChars.append(possibleMatchingChar)
313316
# end if
314317
# end for
@@ -327,11 +330,14 @@ def distanceBetweenChars(firstChar, secondChar):
327330

328331
###################################################################################################
329332
def angleBetweenChars(firstChar, secondChar):
330-
331333
fltAdj = float(abs(firstChar.intCenterX - secondChar.intCenterX))
332334
fltOpp = float(abs(firstChar.intCenterY - secondChar.intCenterY))
333335

334-
fltAngleInRad = math.atan(fltOpp / fltAdj)
336+
if fltAdj != 0.0:
337+
fltAngleInRad = math.atan(fltOpp / fltAdj)
338+
else:
339+
fltAngleInRad = 1.5708
340+
# end if
335341

336342
fltAngleInDeg = fltAngleInRad * (180.0 / math.pi)
337343

@@ -344,10 +350,10 @@ def removeInnerOverlappingChars(listOfMatchingChars):
344350

345351
for currentChar in listOfMatchingChars:
346352
for otherChar in listOfMatchingChars:
347-
if currentChar.contour == otherChar.contour:
348-
if distanceBetweenChars(currentChar, otherChar) < (currentChar.dblDiagonalSize * MIN_DIAG_SIZE_MULTIPLE_AWAY):
353+
if currentChar.contour.all() == otherChar.contour.all():
354+
if distanceBetweenChars(currentChar, otherChar) < (currentChar.fltDiagonalSize * MIN_DIAG_SIZE_MULTIPLE_AWAY):
349355

350-
if currentChar.intRectArea < otherChar.intRectArea:
356+
if currentChar.intBoundingRectArea < otherChar.intBoundingRectArea:
351357
if currentChar in listOfMatchingCharsWithInnerCharRemoved:
352358
listOfMatchingCharsWithInnerCharRemoved.remove(currentChar)
353359
# end if
@@ -368,7 +374,7 @@ def removeInnerOverlappingChars(listOfMatchingChars):
368374
def recognizeCharsInPlate(imgThresh, listOfMatchingChars):
369375
strChars = "" # this will be the return value, the chars in the lic plate
370376

371-
height, width, numChannels = imgThresh.shape
377+
height, width = imgThresh.shape
372378

373379
imgThreshColor = np.zeros((height, width, 3), np.uint8)
374380

@@ -377,17 +383,17 @@ def recognizeCharsInPlate(imgThresh, listOfMatchingChars):
377383
cv2.cvtColor(imgThresh, cv2.COLOR_GRAY2BGR, imgThreshColor)
378384

379385
for currentChar in listOfMatchingChars:
380-
pt1 = tuple(currentChar.boundingRect.x, currentChar.boundingRect.y)
381-
pt2 = tuple((currentChar.boundingRect.x + currentChar.boundingRect.width), (currentChar.boundingRect.y + currentChar.boundingRect.height))
386+
pt1 = (currentChar.intBoundingRectX, currentChar.intBoundingRectY)
387+
pt2 = ((currentChar.intBoundingRectX + currentChar.intBoundingRectWidth), (currentChar.intBoundingRectY + currentChar.intBoundingRectHeight))
382388

383389
cv2.rectangle(imgThreshColor, pt1, pt2, Main.SCALAR_GREEN, 2)
384390

385-
imgROI = imgThresh[currentChar.boundingRect.y : currentChar.boundingRect.y + currentChar.boundingRect.height,
386-
currentChar.boundingRect.x : currentChar.boundingRect.x + currentChar.boundingRect.width]
391+
imgROI = imgThresh[currentChar.intBoundingRectY : currentChar.intBoundingRectY + currentChar.intBoundingRectHeight,
392+
currentChar.intBoundingRectX : currentChar.intBoundingRectX + currentChar.intBoundingRectWidth]
387393

388394
imgROIResized = cv2.resize(imgROI, (RESIZED_CHAR_IMAGE_WIDTH, RESIZED_CHAR_IMAGE_HEIGHT))
389395

390-
npaROIResized = imgROIResized.reshape((1, RESIZED_IMAGE_WIDTH * RESIZED_IMAGE_HEIGHT))
396+
npaROIResized = imgROIResized.reshape((1, RESIZED_CHAR_IMAGE_WIDTH * RESIZED_CHAR_IMAGE_HEIGHT))
391397

392398
npaROIResized = np.float32(npaROIResized)
393399

0 commit comments

Comments
 (0)