Skip to content

Commit

Permalink
Automatic Parking Fare Generator system
Browse files Browse the repository at this point in the history
  • Loading branch information
sagarika4 committed Feb 8, 2020
0 parents commit 6652ea6
Show file tree
Hide file tree
Showing 51 changed files with 2,627 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
Binary file added 0005.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
477 changes: 477 additions & 0 deletions Adafruit_CharLCD.py

Large diffs are not rendered by default.

Binary file added C2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
442 changes: 442 additions & 0 deletions DetectChars.py

Large diffs are not rendered by default.

222 changes: 222 additions & 0 deletions DetectPlates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# DetectPlates.py

import cv2
import numpy as np
import math
import license_plate
import random

import Preprocess
import DetectChars
import PossiblePlate
import PossibleChar

# module level variables ##########################################################################
PLATE_WIDTH_PADDING_FACTOR = 1.3
PLATE_HEIGHT_PADDING_FACTOR = 1.5

###################################################################################################
def detectPlatesInScene(imgOriginalScene):
listOfPossiblePlates = [] # this will be the return value

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()

if license_plate.showSteps == True: # show steps #######################################################
cv2.imshow("0", imgOriginalScene)
# end if # show steps #########################################################################

imgGrayscaleScene, imgThreshScene = Preprocess.preprocess(imgOriginalScene) # preprocess to get grayscale and threshold images

if license_plate.showSteps == True: # show steps #######################################################
cv2.imshow("1a", imgGrayscaleScene)
cv2.imshow("1b", imgThreshScene)
# end if # show steps #########################################################################

# find all possible chars in the scene,
# this function first finds all contours, then only includes contours that could be chars (without comparison to other chars yet)
listOfPossibleCharsInScene = findPossibleCharsInScene(imgThreshScene)

if license_plate.showSteps == True: # show steps #######################################################
print( "step 2 - len(listOfPossibleCharsInScene) = " + str(len(listOfPossibleCharsInScene))) # 131 with MCLRNF1 image

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

contours = []

for possibleChar in listOfPossibleCharsInScene:
contours.append(possibleChar.contour)
# end for

cv2.drawContours(imgContours, contours, -1, license_plate.SCALAR_WHITE)
cv2.imshow("2b", imgContours)
# end if # show steps #########################################################################

# given a list of all possible chars, find groups of matching chars
# in the next steps each group of matching chars will attempt to be recognized as a plate
listOfListsOfMatchingCharsInScene = DetectChars.findListOfListsOfMatchingChars(listOfPossibleCharsInScene)

if license_plate.showSteps == True: # show steps #######################################################
print ("step 3 - listOfListsOfMatchingCharsInScene.Count = " + str(len(listOfListsOfMatchingCharsInScene))) # 13 with MCLRNF1 image

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

for listOfMatchingChars in listOfListsOfMatchingCharsInScene:
intRandomBlue = random.randint(0, 255)
intRandomGreen = random.randint(0, 255)
intRandomRed = random.randint(0, 255)

contours = []

for matchingChar in listOfMatchingChars:
contours.append(matchingChar.contour)
# end for

cv2.drawContours(imgContours, contours, -1, (intRandomBlue, intRandomGreen, intRandomRed))
# end for

cv2.imshow("3", imgContours)
# end if # show steps #########################################################################

for listOfMatchingChars in listOfListsOfMatchingCharsInScene: # for each group of matching chars
possiblePlate = extractPlate(imgOriginalScene, listOfMatchingChars) # attempt to extract plate

if possiblePlate.imgPlate is not None: # if plate was found
listOfPossiblePlates.append(possiblePlate) # add to list of possible plates
# end if
# end for

'''print ("\n" + str(len(listOfPossiblePlates)) + " possible plates found")'''
print ("Number Plate Detected")
# 13 with MCLRNF1 image

if license_plate.showSteps == True: # show steps #######################################################
print ("\n")
cv2.imshow("4a", imgContours)

for i in range(0, len(listOfPossiblePlates)):
p2fRectPoints = cv2.boxPoints(listOfPossiblePlates[i].rrLocationOfPlateInScene)

cv2.line(imgContours, tuple(p2fRectPoints[0]), tuple(p2fRectPoints[1]), license_plate.SCALAR_RED, 2)
cv2.line(imgContours, tuple(p2fRectPoints[1]), tuple(p2fRectPoints[2]), license_plate.SCALAR_RED, 2)
cv2.line(imgContours, tuple(p2fRectPoints[2]), tuple(p2fRectPoints[3]), license_plate.SCALAR_RED, 2)
cv2.line(imgContours, tuple(p2fRectPoints[3]), tuple(p2fRectPoints[0]), license_plate.SCALAR_RED, 2)

cv2.imshow("4a", imgContours)

print ("possible plate " + str(i) + ", click on any image and press a key to continue . . .")

cv2.imshow("4b", listOfPossiblePlates[i].imgPlate)
cv2.waitKey(0)
# end for

print ("\nplate detection complete, click on any image and press a key to begin char recognition . . .\n")
cv2.waitKey(0)
# end if # show steps #########################################################################

return listOfPossiblePlates
# end function

###################################################################################################
def findPossibleCharsInScene(imgThresh):
listOfPossibleChars = [] # this will be the return value

intCountOfPossibleChars = 0

imgThreshCopy = imgThresh.copy()

imgContours, contours, npaHierarchy = cv2.findContours(imgThreshCopy, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # find all contours

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

for i in range(0, len(contours)): # for each contour

if license_plate.showSteps == True: # show steps ###################################################
cv2.drawContours(imgContours, contours, i, license_plate.SCALAR_WHITE)
# end if # show steps #####################################################################

possibleChar = PossibleChar.PossibleChar(contours[i])

if DetectChars.checkIfPossibleChar(possibleChar): # if contour is a possible char, note this does not compare to other chars (yet) . . .
intCountOfPossibleChars = intCountOfPossibleChars + 1 # increment count of possible chars
listOfPossibleChars.append(possibleChar) # and add to list of possible chars
# end if
# end for

if license_plate.showSteps == True: # show steps #######################################################
print ("\nstep 2 - len(contours) = " + str(len(contours))) # 2362 with MCLRNF1 image
print ("step 2 - intCountOfPossibleChars = " + str(intCountOfPossibleChars)) # 131 with MCLRNF1 image
cv2.imshow("2a", imgContours)
# end if # show steps #########################################################################

return listOfPossibleChars
# end function


###################################################################################################
def extractPlate(imgOriginal, listOfMatchingChars):
possiblePlate = PossiblePlate.PossiblePlate() # this will be the return value

listOfMatchingChars.sort(key = lambda matchingChar: matchingChar.intCenterX) # sort chars from left to right based on x position

# calculate the center point of the plate
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

# calculate plate width and height
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
# end for

fltAverageCharHeight = intTotalOfCharHeights / len(listOfMatchingChars)

intPlateHeight = int(fltAverageCharHeight * PLATE_HEIGHT_PADDING_FACTOR)

# calculate correction angle of plate region
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)

# pack plate region center point, width and height, and correction angle into rotated rect member variable of plate
possiblePlate.rrLocationOfPlateInScene = ( tuple(ptPlateCenter), (intPlateWidth, intPlateHeight), fltCorrectionAngleInDeg )

# final steps are to perform the actual rotation

# get the rotation matrix for our calculated correction angle
rotationMatrix = cv2.getRotationMatrix2D(tuple(ptPlateCenter), fltCorrectionAngleInDeg, 1.0)

height, width, numChannels = imgOriginal.shape # unpack original image width and height

imgRotated = cv2.warpAffine(imgOriginal, rotationMatrix, (width, height)) # rotate the entire image

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

possiblePlate.imgPlate = imgCropped # copy the cropped plate image into the applicable member variable of the possible plate

return possiblePlate
# end function












5 changes: 5 additions & 0 deletions Fare Calculation.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
License_Plate_Number,Vehicle Type,Entry Time
IC8S,Bike,1525341533.931944
H14FE5621,Bike,1525342067.0251193
III,Car,1525343747.0427272
MCLRNF1,Car,1525415658.5371869
41 changes: 41 additions & 0 deletions PossibleChar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# PossibleChar.py

import cv2
import numpy as np
import math

###################################################################################################
class PossibleChar:

# constructor #################################################################################
def __init__(self, _contour):
self.contour = _contour

self.boundingRect = cv2.boundingRect(self.contour)

[intX, intY, intWidth, intHeight] = self.boundingRect

self.intBoundingRectX = intX
self.intBoundingRectY = intY
self.intBoundingRectWidth = intWidth
self.intBoundingRectHeight = intHeight

self.intBoundingRectArea = self.intBoundingRectWidth * self.intBoundingRectHeight

self.intCenterX = (self.intBoundingRectX + self.intBoundingRectX + self.intBoundingRectWidth) / 2
self.intCenterY = (self.intBoundingRectY + self.intBoundingRectY + self.intBoundingRectHeight) / 2

self.fltDiagonalSize = math.sqrt((self.intBoundingRectWidth ** 2) + (self.intBoundingRectHeight ** 2))

self.fltAspectRatio = float(self.intBoundingRectWidth) / float(self.intBoundingRectHeight)
# end constructor

# end class








24 changes: 24 additions & 0 deletions PossiblePlate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# PossiblePlate.py

import cv2
import numpy as np

###################################################################################################
class PossiblePlate:

# constructor #################################################################################
def __init__(self):
self.imgPlate = None
self.imgGrayscale = None
self.imgThresh = None

self.rrLocationOfPlateInScene = None

self.strChars = ""
# end constructor

# end class




69 changes: 69 additions & 0 deletions Preprocess.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Preprocess.py

import cv2
import numpy as np
import math

# module level variables ##########################################################################
GAUSSIAN_SMOOTH_FILTER_SIZE = (5, 5)
ADAPTIVE_THRESH_BLOCK_SIZE = 19
ADAPTIVE_THRESH_WEIGHT = 9

###################################################################################################
def preprocess(imgOriginal):
imgGrayscale = extractValue(imgOriginal)

imgMaxContrastGrayscale = maximizeContrast(imgGrayscale)

height, width = imgGrayscale.shape

imgBlurred = np.zeros((height, width, 1), np.uint8)

imgBlurred = cv2.GaussianBlur(imgMaxContrastGrayscale, GAUSSIAN_SMOOTH_FILTER_SIZE, 0)

imgThresh = cv2.adaptiveThreshold(imgBlurred, 255.0, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, ADAPTIVE_THRESH_BLOCK_SIZE, ADAPTIVE_THRESH_WEIGHT)

return imgGrayscale, imgThresh
# end function

###################################################################################################
def extractValue(imgOriginal):
height, width, numChannels = imgOriginal.shape

imgHSV = np.zeros((height, width, 3), np.uint8)

imgHSV = cv2.cvtColor(imgOriginal, cv2.COLOR_BGR2HSV)

imgHue, imgSaturation, imgValue = cv2.split(imgHSV)

return imgValue
# end function

###################################################################################################
def maximizeContrast(imgGrayscale):

height, width = imgGrayscale.shape

imgTopHat = np.zeros((height, width, 1), np.uint8)
imgBlackHat = np.zeros((height, width, 1), np.uint8)

structuringElement = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

imgTopHat = cv2.morphologyEx(imgGrayscale, cv2.MORPH_TOPHAT, structuringElement)
imgBlackHat = cv2.morphologyEx(imgGrayscale, cv2.MORPH_BLACKHAT, structuringElement)

imgGrayscalePlusTopHat = cv2.add(imgGrayscale, imgTopHat)
imgGrayscalePlusTopHatMinusBlackHat = cv2.subtract(imgGrayscalePlusTopHat, imgBlackHat)

return imgGrayscalePlusTopHatMinusBlackHat
# end function










Binary file added __pycache__/DetectChars.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/DetectChars.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/DetectPlates.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/DetectPlates.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/Main.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/PossibleChar.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/PossibleChar.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/PossiblePlate.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/PossiblePlate.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/Preprocess.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/Preprocess.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/fare_calculator.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/fare_calculator.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/identify_vehicle.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/identify_vehicle.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/imagenet_utils.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/imagenet_utils.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/license_plate.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/license_plate.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/loadModel.cpython-35.pyc
Binary file not shown.
Binary file added __pycache__/loadModel.cpython-36.pyc
Binary file not shown.
Binary file added __pycache__/resnet50.cpython-36.pyc
Binary file not shown.
Binary file added b.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added b1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added car.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 6652ea6

Please sign in to comment.