Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
2
22_23-J-84
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
KSH.Mohamed
22_23-J-84
Commits
23aa7962
Commit
23aa7962
authored
May 26, 2023
by
Bogahawatta L.B.G.D.P.K
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upload New File
parent
3d44300b
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
362 additions
and
0 deletions
+362
-0
DetectChars.py
DetectChars.py
+362
-0
No files found.
DetectChars.py
0 → 100644
View file @
23aa7962
import
os
import
cv2
import
numpy
as
np
import
math
import
random
import
Main
import
Preprocess
import
PossibleChar
kNearest
=
cv2
.
ml
.
KNearest_create
()
MIN_PIXEL_WIDTH
=
2
MIN_PIXEL_HEIGHT
=
8
MIN_ASPECT_RATIO
=
0.25
MAX_ASPECT_RATIO
=
1.0
MIN_PIXEL_AREA
=
80
MIN_DIAG_SIZE_MULTIPLE_AWAY
=
0.3
MAX_DIAG_SIZE_MULTIPLE_AWAY
=
5.0
MAX_CHANGE_IN_AREA
=
0.5
MAX_CHANGE_IN_WIDTH
=
0.8
MAX_CHANGE_IN_HEIGHT
=
0.2
MAX_ANGLE_BETWEEN_CHARS
=
12.0
MIN_NUMBER_OF_MATCHING_CHARS
=
3
RESIZED_CHAR_IMAGE_WIDTH
=
20
RESIZED_CHAR_IMAGE_HEIGHT
=
30
MIN_CONTOUR_AREA
=
100
def
loadKNNDataAndTrainKNN
():
try
:
npaClassifications
=
np
.
loadtxt
(
"classifications.txt"
,
np
.
float32
)
except
:
print
(
"error, unable to open classifications.txt, exiting program
\n
"
)
os
.
system
(
"pause"
)
return
False
# end try
try
:
npaFlattenedImages
=
np
.
loadtxt
(
"flattened_images.txt"
,
np
.
float32
)
except
:
print
(
"error, unable to open flattened_images.txt, exiting program
\n
"
)
os
.
system
(
"pause"
)
return
False
# end try
npaClassifications
=
npaClassifications
.
reshape
((
npaClassifications
.
size
,
1
))
kNearest
.
setDefaultK
(
1
)
kNearest
.
train
(
npaFlattenedImages
,
cv2
.
ml
.
ROW_SAMPLE
,
npaClassifications
)
return
True
def
detectCharsInPlates
(
listOfPossiblePlates
):
intPlateCounter
=
0
imgContours
=
None
contours
=
[]
if
len
(
listOfPossiblePlates
)
==
0
:
return
listOfPossiblePlates
for
possiblePlate
in
listOfPossiblePlates
:
possiblePlate
.
imgGrayscale
,
possiblePlate
.
imgThresh
=
Preprocess
.
preprocess
(
possiblePlate
.
imgPlate
)
if
Main
.
showSteps
==
True
:
cv2
.
imshow
(
"5a"
,
possiblePlate
.
imgPlate
)
cv2
.
imshow
(
"5b"
,
possiblePlate
.
imgGrayscale
)
cv2
.
imshow
(
"5c"
,
possiblePlate
.
imgThresh
)
possiblePlate
.
imgThresh
=
cv2
.
resize
(
possiblePlate
.
imgThresh
,
(
0
,
0
),
fx
=
1.6
,
fy
=
1.6
)
thresholdValue
,
possiblePlate
.
imgThresh
=
cv2
.
threshold
(
possiblePlate
.
imgThresh
,
0.0
,
255.0
,
cv2
.
THRESH_BINARY
|
cv2
.
THRESH_OTSU
)
if
Main
.
showSteps
==
True
:
cv2
.
imshow
(
"5d"
,
possiblePlate
.
imgThresh
)
listOfPossibleCharsInPlate
=
findPossibleCharsInPlate
(
possiblePlate
.
imgGrayscale
,
possiblePlate
.
imgThresh
)
if
Main
.
showSteps
==
True
:
height
,
width
,
numChannels
=
possiblePlate
.
imgPlate
.
shape
imgContours
=
np
.
zeros
((
height
,
width
,
3
),
np
.
uint8
)
del
contours
[:]
for
possibleChar
in
listOfPossibleCharsInPlate
:
contours
.
append
(
possibleChar
.
contour
)
# end for
cv2
.
drawContours
(
imgContours
,
contours
,
-
1
,
Main
.
SCALAR_WHITE
)
cv2
.
imshow
(
"6"
,
imgContours
)
listOfListsOfMatchingCharsInPlate
=
findListOfListsOfMatchingChars
(
listOfPossibleCharsInPlate
)
if
Main
.
showSteps
==
True
:
imgContours
=
np
.
zeros
((
height
,
width
,
3
),
np
.
uint8
)
del
contours
[:]
for
listOfMatchingChars
in
listOfListsOfMatchingCharsInPlate
:
intRandomBlue
=
random
.
randint
(
0
,
255
)
intRandomGreen
=
random
.
randint
(
0
,
255
)
intRandomRed
=
random
.
randint
(
0
,
255
)
for
matchingChar
in
listOfMatchingChars
:
contours
.
append
(
matchingChar
.
contour
)
cv2
.
drawContours
(
imgContours
,
contours
,
-
1
,
(
intRandomBlue
,
intRandomGreen
,
intRandomRed
))
cv2
.
imshow
(
"7"
,
imgContours
)
if
(
len
(
listOfListsOfMatchingCharsInPlate
)
==
0
):
if
Main
.
showSteps
==
True
:
print
(
"chars found in plate number "
+
str
(
intPlateCounter
)
+
" = (none), click on any image and press a key to continue . . ."
)
intPlateCounter
=
intPlateCounter
+
1
cv2
.
destroyWindow
(
"8"
)
cv2
.
destroyWindow
(
"9"
)
cv2
.
destroyWindow
(
"10"
)
cv2
.
waitKey
(
0
)
possiblePlate
.
strChars
=
""
continue
for
i
in
range
(
0
,
len
(
listOfListsOfMatchingCharsInPlate
)):
listOfListsOfMatchingCharsInPlate
[
i
]
.
sort
(
key
=
lambda
matchingChar
:
matchingChar
.
intCenterX
)
listOfListsOfMatchingCharsInPlate
[
i
]
=
removeInnerOverlappingChars
(
listOfListsOfMatchingCharsInPlate
[
i
])
if
Main
.
showSteps
==
True
:
imgContours
=
np
.
zeros
((
height
,
width
,
3
),
np
.
uint8
)
for
listOfMatchingChars
in
listOfListsOfMatchingCharsInPlate
:
intRandomBlue
=
random
.
randint
(
0
,
255
)
intRandomGreen
=
random
.
randint
(
0
,
255
)
intRandomRed
=
random
.
randint
(
0
,
255
)
del
contours
[:]
for
matchingChar
in
listOfMatchingChars
:
contours
.
append
(
matchingChar
.
contour
)
cv2
.
drawContours
(
imgContours
,
contours
,
-
1
,
(
intRandomBlue
,
intRandomGreen
,
intRandomRed
))
cv2
.
imshow
(
"8"
,
imgContours
)
intLenOfLongestListOfChars
=
0
intIndexOfLongestListOfChars
=
0
for
i
in
range
(
0
,
len
(
listOfListsOfMatchingCharsInPlate
)):
if
len
(
listOfListsOfMatchingCharsInPlate
[
i
])
>
intLenOfLongestListOfChars
:
intLenOfLongestListOfChars
=
len
(
listOfListsOfMatchingCharsInPlate
[
i
])
intIndexOfLongestListOfChars
=
i
longestListOfMatchingCharsInPlate
=
listOfListsOfMatchingCharsInPlate
[
intIndexOfLongestListOfChars
]
if
Main
.
showSteps
==
True
:
imgContours
=
np
.
zeros
((
height
,
width
,
3
),
np
.
uint8
)
del
contours
[:]
for
matchingChar
in
longestListOfMatchingCharsInPlate
:
contours
.
append
(
matchingChar
.
contour
)
cv2
.
drawContours
(
imgContours
,
contours
,
-
1
,
Main
.
SCALAR_WHITE
)
cv2
.
imshow
(
"9"
,
imgContours
)
possiblePlate
.
strChars
=
recognizeCharsInPlate
(
possiblePlate
.
imgThresh
,
longestListOfMatchingCharsInPlate
)
if
Main
.
showSteps
==
True
:
print
(
"chars found in plate number "
+
str
(
intPlateCounter
)
+
" = "
+
possiblePlate
.
strChars
+
", click on any image and press a key to continue . . ."
)
intPlateCounter
=
intPlateCounter
+
1
cv2
.
waitKey
(
0
)
if
Main
.
showSteps
==
True
:
print
(
"
\n
char detection complete, click on any image and press a key to continue . . .
\n
"
)
cv2
.
waitKey
(
0
)
return
listOfPossiblePlates
def
findPossibleCharsInPlate
(
imgGrayscale
,
imgThresh
):
listOfPossibleChars
=
[]
contours
=
[]
imgThreshCopy
=
imgThresh
.
copy
()
contours
,
npaHierarchy
=
cv2
.
findContours
(
imgThreshCopy
,
cv2
.
RETR_LIST
,
cv2
.
CHAIN_APPROX_SIMPLE
)
for
contour
in
contours
:
possibleChar
=
PossibleChar
.
PossibleChar
(
contour
)
if
checkIfPossibleChar
(
possibleChar
):
listOfPossibleChars
.
append
(
possibleChar
)
return
listOfPossibleChars
def
checkIfPossibleChar
(
possibleChar
):
if
(
possibleChar
.
intBoundingRectArea
>
MIN_PIXEL_AREA
and
possibleChar
.
intBoundingRectWidth
>
MIN_PIXEL_WIDTH
and
possibleChar
.
intBoundingRectHeight
>
MIN_PIXEL_HEIGHT
and
MIN_ASPECT_RATIO
<
possibleChar
.
fltAspectRatio
and
possibleChar
.
fltAspectRatio
<
MAX_ASPECT_RATIO
):
return
True
else
:
return
False
def
findListOfListsOfMatchingChars
(
listOfPossibleChars
):
listOfListsOfMatchingChars
=
[]
for
possibleChar
in
listOfPossibleChars
:
listOfMatchingChars
=
findListOfMatchingChars
(
possibleChar
,
listOfPossibleChars
)
listOfMatchingChars
.
append
(
possibleChar
)
if
len
(
listOfMatchingChars
)
<
MIN_NUMBER_OF_MATCHING_CHARS
:
continue
listOfListsOfMatchingChars
.
append
(
listOfMatchingChars
)
listOfPossibleCharsWithCurrentMatchesRemoved
=
[]
listOfPossibleCharsWithCurrentMatchesRemoved
=
list
(
set
(
listOfPossibleChars
)
-
set
(
listOfMatchingChars
))
recursiveListOfListsOfMatchingChars
=
findListOfListsOfMatchingChars
(
listOfPossibleCharsWithCurrentMatchesRemoved
)
for
recursiveListOfMatchingChars
in
recursiveListOfListsOfMatchingChars
:
listOfListsOfMatchingChars
.
append
(
recursiveListOfMatchingChars
)
break
return
listOfListsOfMatchingChars
def
findListOfMatchingChars
(
possibleChar
,
listOfChars
):
listOfMatchingChars
=
[]
for
possibleMatchingChar
in
listOfChars
:
if
possibleMatchingChar
==
possibleChar
:
continue
fltDistanceBetweenChars
=
distanceBetweenChars
(
possibleChar
,
possibleMatchingChar
)
fltAngleBetweenChars
=
angleBetweenChars
(
possibleChar
,
possibleMatchingChar
)
fltChangeInArea
=
float
(
abs
(
possibleMatchingChar
.
intBoundingRectArea
-
possibleChar
.
intBoundingRectArea
))
/
float
(
possibleChar
.
intBoundingRectArea
)
fltChangeInWidth
=
float
(
abs
(
possibleMatchingChar
.
intBoundingRectWidth
-
possibleChar
.
intBoundingRectWidth
))
/
float
(
possibleChar
.
intBoundingRectWidth
)
fltChangeInHeight
=
float
(
abs
(
possibleMatchingChar
.
intBoundingRectHeight
-
possibleChar
.
intBoundingRectHeight
))
/
float
(
possibleChar
.
intBoundingRectHeight
)
if
(
fltDistanceBetweenChars
<
(
possibleChar
.
fltDiagonalSize
*
MAX_DIAG_SIZE_MULTIPLE_AWAY
)
and
fltAngleBetweenChars
<
MAX_ANGLE_BETWEEN_CHARS
and
fltChangeInArea
<
MAX_CHANGE_IN_AREA
and
fltChangeInWidth
<
MAX_CHANGE_IN_WIDTH
and
fltChangeInHeight
<
MAX_CHANGE_IN_HEIGHT
):
listOfMatchingChars
.
append
(
possibleMatchingChar
)
return
listOfMatchingChars
def
distanceBetweenChars
(
firstChar
,
secondChar
):
intX
=
abs
(
firstChar
.
intCenterX
-
secondChar
.
intCenterX
)
intY
=
abs
(
firstChar
.
intCenterY
-
secondChar
.
intCenterY
)
return
math
.
sqrt
((
intX
**
2
)
+
(
intY
**
2
))
def
angleBetweenChars
(
firstChar
,
secondChar
):
fltAdj
=
float
(
abs
(
firstChar
.
intCenterX
-
secondChar
.
intCenterX
))
fltOpp
=
float
(
abs
(
firstChar
.
intCenterY
-
secondChar
.
intCenterY
))
if
fltAdj
!=
0.0
:
fltAngleInRad
=
math
.
atan
(
fltOpp
/
fltAdj
)
else
:
fltAngleInRad
=
1.5708
fltAngleInDeg
=
fltAngleInRad
*
(
180.0
/
math
.
pi
)
return
fltAngleInDeg
def
removeInnerOverlappingChars
(
listOfMatchingChars
):
listOfMatchingCharsWithInnerCharRemoved
=
list
(
listOfMatchingChars
)
for
currentChar
in
listOfMatchingChars
:
for
otherChar
in
listOfMatchingChars
:
if
currentChar
!=
otherChar
:
if
distanceBetweenChars
(
currentChar
,
otherChar
)
<
(
currentChar
.
fltDiagonalSize
*
MIN_DIAG_SIZE_MULTIPLE_AWAY
):
if
currentChar
.
intBoundingRectArea
<
otherChar
.
intBoundingRectArea
:
if
currentChar
in
listOfMatchingCharsWithInnerCharRemoved
:
listOfMatchingCharsWithInnerCharRemoved
.
remove
(
currentChar
)
# end if
else
:
if
otherChar
in
listOfMatchingCharsWithInnerCharRemoved
:
listOfMatchingCharsWithInnerCharRemoved
.
remove
(
otherChar
)
return
listOfMatchingCharsWithInnerCharRemoved
def
recognizeCharsInPlate
(
imgThresh
,
listOfMatchingChars
):
strChars
=
""
height
,
width
=
imgThresh
.
shape
imgThreshColor
=
np
.
zeros
((
height
,
width
,
3
),
np
.
uint8
)
listOfMatchingChars
.
sort
(
key
=
lambda
matchingChar
:
matchingChar
.
intCenterX
)
cv2
.
cvtColor
(
imgThresh
,
cv2
.
COLOR_GRAY2BGR
,
imgThreshColor
)
for
currentChar
in
listOfMatchingChars
:
pt1
=
(
currentChar
.
intBoundingRectX
,
currentChar
.
intBoundingRectY
)
pt2
=
((
currentChar
.
intBoundingRectX
+
currentChar
.
intBoundingRectWidth
),
(
currentChar
.
intBoundingRectY
+
currentChar
.
intBoundingRectHeight
))
cv2
.
rectangle
(
imgThreshColor
,
pt1
,
pt2
,
Main
.
SCALAR_GREEN
,
2
)
# crop char out of threshold image
imgROI
=
imgThresh
[
currentChar
.
intBoundingRectY
:
currentChar
.
intBoundingRectY
+
currentChar
.
intBoundingRectHeight
,
currentChar
.
intBoundingRectX
:
currentChar
.
intBoundingRectX
+
currentChar
.
intBoundingRectWidth
]
imgROIResized
=
cv2
.
resize
(
imgROI
,
(
RESIZED_CHAR_IMAGE_WIDTH
,
RESIZED_CHAR_IMAGE_HEIGHT
))
npaROIResized
=
imgROIResized
.
reshape
((
1
,
RESIZED_CHAR_IMAGE_WIDTH
*
RESIZED_CHAR_IMAGE_HEIGHT
))
npaROIResized
=
np
.
float32
(
npaROIResized
)
retval
,
npaResults
,
neigh_resp
,
dists
=
kNearest
.
findNearest
(
npaROIResized
,
k
=
1
)
strCurrentChar
=
str
(
chr
(
int
(
npaResults
[
0
][
0
])))
strChars
=
strChars
+
strCurrentChar
if
Main
.
showSteps
==
True
:
cv2
.
imshow
(
"10"
,
imgThreshColor
)
return
strChars
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment