Skip to content
Permalink
Browse files
Disso Code
  • Loading branch information
prices25 committed Aug 3, 2020
0 parents commit d0edc357441df5c657c90b7eedd721873b820122
Show file tree
Hide file tree
Showing 5 changed files with 529 additions and 0 deletions.
@@ -0,0 +1,243 @@
import os

import cv2
import numpy as np
import math
import random

import Main
import Preprocess
import PossibleChar

kNearest = cv2.ml.KNearest_create()

m_p_w = 2 # min pixel width
m_p_h = 8 #min pixel height

min_a_r = 0.25 # min aspect ratio
max_a_r = 1.0 # max aspect ratio

m_p_a = 80 # min pixel area

# min and max diag size multiple away
min_d_s_m_a = 0.3
max_d_s_m_a = 5.0

max_c_i_a = 0.5

max_c_i_w = 0.8
max_c_i_h = 0.2

max_a_b_c = 12.0

min_n_o_m_c = 3

r_c_i_w = 20
r_c_i_h = 30

MIN_CONTOUR_AREA = 100

def findPossibleCharsInPlate(imgGrayscale, imgThresh):
PossCharsList = []
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):
PossCharsList.append(possibleChar)

return PossCharsList

def checkIfPossibleChar(possibleChar):

if (possibleChar.intBoundingRectArea > m_p_a and
possibleChar.intBoundingRectWidth > m_p_w and possibleChar.intBoundingRectHeight > m_p_h and
min_a_r < possibleChar.fltAspectRatio and possibleChar.fltAspectRatio < max_a_r):
return True
else:
return False

def findrecursLOMatchChars(PossCharsList):

recursLOMatchChars = []

for possibleChar in PossCharsList:
listOfMatchingChars = findListOfMatchingChars(possibleChar, PossCharsList)

listOfMatchingChars.append(possibleChar)

if len(listOfMatchingChars) < min_n_o_m_c:
continue

recursLOMatchChars.append(listOfMatchingChars)

PossCharsListWithCurrentMatchesRemoved = []
PossCharsListWithCurrentMatchesRemoved = list(set(PossCharsList) - set(listOfMatchingChars))

recursiveListOfMatchingChars = findrecursLOMatchChars(PossCharsListWithCurrentMatchesRemoved)

for recursiveListOfMatchingChars in recursiveListOfMatchingChars:
recursLOMatchChars.append(recursiveListOfMatchingChars)
break

return recursLOMatchChars

def detectCharsInPlates(listOfpossPlates):
intPlateCounter = 0
imgContours = None
contours = []

if len(listOfpossPlates) == 0:
return listOfpossPlates




for possPlate in listOfpossPlates:

possPlate.imgGrayscale, possPlate.imgThresh = Preprocess.preprocess(possPlate.imgPlate)
possPlate.imgThresh = cv2.resize(possPlate.imgThresh, (0, 0), fx = 1.6, fy = 1.6)
thresholdValue, possPlate.imgThresh = cv2.threshold(possPlate.imgThresh, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
PossCharsListInPlate = findPossibleCharsInPlate(possPlate.imgGrayscale, possPlate.imgThresh)
recursLOMatchCharsInPlate = findrecursLOMatchChars(PossCharsListInPlate)

if (len(recursLOMatchCharsInPlate) == 0):
possPlate.strChars = ""
continue

for i in range(0, len(recursLOMatchCharsInPlate)):
recursLOMatchCharsInPlate[i].sort(key = lambda matchingChar: matchingChar.intCenterX)
recursLOMatchCharsInPlate[i] = removeInnerOverlappingChars(recursLOMatchCharsInPlate[i])
intLenOfLongestListOfChars = 0
intIndexOfLongestListOfChars = 0
for i in range(0, len(recursLOMatchCharsInPlate)):
if len(recursLOMatchCharsInPlate[i]) > intLenOfLongestListOfChars:
intLenOfLongestListOfChars = len(recursLOMatchCharsInPlate[i])
intIndexOfLongestListOfChars = i

longestListOfMatchingCharsInPlate = recursLOMatchCharsInPlate[intIndexOfLongestListOfChars]

possPlate.strChars = recognizeCharsInPlate(possPlate.imgThresh, longestListOfMatchingCharsInPlate)

return listOfpossPlates

def loadKNNDataAndTrainKNN():
try:
npaClass = np.loadtxt("classifications.txt", np.float32)
except:
print("error, cant open classifications.txt, exiting program\n")
os.system("pause")
return False

try:
npaFlattenedImages = np.loadtxt("flattened_images.txt", np.float32)
except:
print("error, cant open flattened_images.txt, exiting program\n")
os.system("pause")
return False

npaClass = npaClass.reshape((npaClass.size, 1))
kNearest.setDefaultK(1)
kNearest.train(npaFlattenedImages, cv2.ml.ROW_SAMPLE, npaClass)

return True



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_d_s_m_a) and
fltAngleBetweenChars < max_a_b_c and
fltChangeInArea < max_c_i_a and
fltChangeInWidth < max_c_i_w and
fltChangeInHeight < max_c_i_h):

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_d_s_m_a):
if currentChar.intBoundingRectArea < otherChar.intBoundingRectArea:
if currentChar in listOfMatchingCharsWithInnerCharRemoved:
listOfMatchingCharsWithInnerCharRemoved.remove(currentChar)
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)

imgROI = imgThresh[currentChar.intBoundingRectY : currentChar.intBoundingRectY + currentChar.intBoundingRectHeight,
currentChar.intBoundingRectX : currentChar.intBoundingRectX + currentChar.intBoundingRectWidth]

imgROIResized = cv2.resize(imgROI, (r_c_i_w, r_c_i_h))

npaROIResized = imgROIResized.reshape((1, r_c_i_w * r_c_i_h))

npaROIResized = np.float32(npaROIResized)

retval, npaResults, neigh_resp, dists = kNearest.findNearest(npaROIResized, k = 1)

strCurrentChar = str(chr(int(npaResults[0][0])))

strChars = strChars + strCurrentChar

return strChars
@@ -0,0 +1,98 @@
# DetectPlates.py

import cv2
import numpy as np
import math
import Main
import random

import Preprocess
import DetectChars
import PossiblePlate
import PossibleChar

PLATE_WIDTH_PADDING_FACTOR = 1.3
PLATE_HEIGHT_PADDING_FACTOR = 1.5


def findPossibleCharsInScene(imgThresh):
listOfPossibleChars = []

intCountOfPossibleChars = 0

imgThreshCopy = imgThresh.copy()

contours, npaHierarchy = cv2.findContours(imgThreshCopy, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

height, width = imgThresh.shape
imgContours = np.zeros((height, width, 3), np.uint8)

for i in range(0, len(contours)):

possibleChar = PossibleChar.PossibleChar(contours[i])

if DetectChars.checkIfPossibleChar(possibleChar):
intCountOfPossibleChars = intCountOfPossibleChars + 1
listOfPossibleChars.append(possibleChar)
return listOfPossibleChars


def extractPlate(imgOriginal, listOfMatchingChars):
possiblePlate = PossiblePlate.PossiblePlate()

listOfMatchingChars.sort(key = lambda matchingChar: matchingChar.intCenterX)

fltPlateCenterX = (listOfMatchingChars[0].intCenterX + listOfMatchingChars[len(listOfMatchingChars) - 1].intCenterX) / 2.0
fltPlateCenterY = (listOfMatchingChars[0].intCenterY + listOfMatchingChars[len(listOfMatchingChars) - 1].intCenterY) / 2.0

ptPlateCenter = fltPlateCenterX, fltPlateCenterY

intPlateWidth = int((listOfMatchingChars[len(listOfMatchingChars) - 1].intBoundingRectX + listOfMatchingChars[len(listOfMatchingChars) - 1].intBoundingRectWidth - listOfMatchingChars[0].intBoundingRectX) * PLATE_WIDTH_PADDING_FACTOR)

intTotalOfCharHeights = 0

for matchingChar in listOfMatchingChars:
intTotalOfCharHeights = intTotalOfCharHeights + matchingChar.intBoundingRectHeight

fltAverageCharHeight = intTotalOfCharHeights / len(listOfMatchingChars)

intPlateHeight = int(fltAverageCharHeight * PLATE_HEIGHT_PADDING_FACTOR)

fltOpposite = listOfMatchingChars[len(listOfMatchingChars) - 1].intCenterY - listOfMatchingChars[0].intCenterY
fltHypotenuse = DetectChars.distanceBetweenChars(listOfMatchingChars[0], listOfMatchingChars[len(listOfMatchingChars) - 1])
fltCorrectionAngleInRad = math.asin(fltOpposite / fltHypotenuse)
fltCorrectionAngleInDeg = fltCorrectionAngleInRad * (180.0 / math.pi)

possiblePlate.rrLocationOfPlateInScene = ( tuple(ptPlateCenter), (intPlateWidth, intPlateHeight), fltCorrectionAngleInDeg )

rotationMatrix = cv2.getRotationMatrix2D(tuple(ptPlateCenter), fltCorrectionAngleInDeg, 1.0)

height, width, numChannels = imgOriginal.shape

imgRotated = cv2.warpAffine(imgOriginal, rotationMatrix, (width, height))

imgCropped = cv2.getRectSubPix(imgRotated, (intPlateWidth, intPlateHeight), tuple(ptPlateCenter))

possiblePlate.imgPlate = imgCropped

return possiblePlate

def detectPlatesInScene(imgOriginalScene):
listOfPossiblePlates = []
height, width, numChannels = imgOriginalScene.shape

imgGrayscaleScene = np.zeros((height, width, 1), np.uint8)
imgThreshScene = np.zeros((height, width, 1), np.uint8)
imgContours = np.zeros((height, width, 3), np.uint8)

cv2.destroyAllWindows()
imgGrayscaleScene, imgThreshScene = Preprocess.preprocess(imgOriginalScene)
listOfPossibleCharsInScene = findPossibleCharsInScene(imgThreshScene)
listOfListsOfMatchingCharsInScene = DetectChars.findListOfListsOfMatchingChars(listOfPossibleCharsInScene)
print(5)
for listOfMatchingChars in listOfListsOfMatchingCharsInScene:
possiblePlate = extractPlate(imgOriginalScene, listOfMatchingChars)

if possiblePlate.imgPlate is not None:
listOfPossiblePlates.append(possiblePlate)
return listOfPossiblePlates

0 comments on commit d0edc35

Please sign in to comment.