0% found this document useful (0 votes)
21 views

CP4291- IOT Lab Manual

Internet of things

Uploaded by

muthu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views

CP4291- IOT Lab Manual

Internet of things

Uploaded by

muthu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 72

Department of Computer Science and Engineering

CP4291–INTERNET OF THINGS LABORATORY

LABORATORY RECORD

Academic Year: 2022 - 2023

Name : _______________________________________
Reg.No : _________________ Semester : ___________
Degree : _________________ Branch : _______
Subject Code/Name: _____________________________

1
BONAFIDE CERTIFICATE

Name of the Student : _____________________________________________

Register No.

This is to Certify that this is a bonafide record of the work done by the above
student__________________________Semester M.E Degree in
_______________________________________________________________in the
_______________________________________________________________
Laboratory during the academic year 2022-2023.

Faculty-In-Charge Head of the Dept.

Date:

Submitted for the Practical Examination held on __________________

Internal Examiner External Examiner

2
List of content
S.no Date List of Experiment Pg.no Marks signature

Application for LED Blink using Arduino or


1A.
Raspberry Pi

Application for LED Pattern using Arduino or


1B.
Raspberry Pi

Application for LED Pattern with Push Button


2.
Control using Arduino or Raspberry Pi

Application for LM35 Temperature Sensor to


3. display temperature values using Arduino or
Raspberry Pi

Application for Forest fire detection end node


4.
using Raspberry Pi device and sensor

Application for home intrusion detection web


5.
application

Application for Smart parking

6 application using python and Django for

web application

3
Ex.No:1A
LED Blink using Arduino
Date :

Aim:-

To develop an application for LED Blink using Arduino.

Components Required:-
 1 - Breadboard
 1 - Arduino Uno R3
 1 - LED
 1 - 330Ω Resistor
 2 - Jumper

Procedure:-
Follow the circuit diagram and hook up the components on the breadboard as shown in the image
given below.

Note − To find out the polarity of an LED, look at it closely. The shorter of the two legs, towards the
flat edge of the bulb indicates the negative terminal.

4
Components like resistors need to have their terminals bent into 90° angles in order to fit the
breadboard sockets properly. You can also cut the terminals shorter.

Sketch
Open the Arduino IDE software on your computer. Coding in the Arduino language will control your
circuit. Open the new sketch File by clicking New.

5
Arduino Code:-
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
*/
// the setup function runs once when you press reset or power the board
void setup() { // initialize digital pin 13 as an output.
pinMode(2, OUTPUT);}
// the loop function runs over and over again forever
void loop() {
digitalWrite(2, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second}

Code to Note
pinMode(2, OUTPUT) − Before you can use one of Arduino’s pins, you need to tell Arduino Uno
R3 whether it is an INPUT or OUTPUT. We use a built-in “function” called pinMode() to do this.
digitalWrite(2, HIGH) − When you are using a pin as an OUTPUT, you can command it to be
HIGH (output 5 volts), or LOW (output 0 volts).

Result:-
You should see your LED turn on and off. If the required output is not seen, make sure you
have assembled the circuit correctly, and verified and uploaded the code to your board.

6
Ex.No:1B
LED Pattern using Arduino
Date :

Aim:-

To develop an application for LED Blink using Arduino.

Component needed:-
Arduino Uno x 1:

LED x 12:

Jumper wires:

7
Connections:-

Arduino Code:-d paste the code below in Arduino and click upload
void setup()
{
for (int pin = 2; pin <= 12; pin++)
{
pinMode(pin,OUTPUT);
}
}
//Main Loop - Switches different LED Patterns
void loop()
{
int pickme = random(1,20); // picks a random pattern of LED patterns
switch(pickme)
{
case 1:
onrun(random(20,50));
break;
case 2:
alternate(random(80,100));
break;
case 3:
offrun(random(20,50));
break;
case 4:
stack(random(30,50));
break;
case 5:
chaser(random(80,100));

8
break;
case 6:
fadealter(random(80,100));
break;
}
}
void clearall()
{
for (int pin = 2; pin <= 19; pin++)
{
digitalWrite(pin,LOW);
}
}
void fillall()
{
for (int pin = 2; pin <= 19; pin++)
{
digitalWrite(pin, HIGH);
}
}
//One ON LED Run and all other OFF
void onrun(int delaytime)
{
for(int pin = 2; pin <= 19; pin++)
{
clearall();
digitalWrite(pin, HIGH);
delay(delaytime);
}
for(int pin = 18; pin >= 2; pin--)
{
clearall();
digitalWrite(pin, HIGH);
delay(delaytime);
}
}
//One OFF LED Run and all other OFF
void offrun(int delaytime)
{
for(int pin = 2; pin <= 19; pin++)
{
fillall();
digitalWrite(pin, LOW);
delay(delaytime);
}
for(int pin = 18; pin >= 2; pin--)
{
fillall();
digitalWrite(pin, LOW);
delay(delaytime);
}

9
}
//Flashing all LEDs ON and OFF
void flash(int delaytime)
{
for(int i = 1; i <=20; i++)
{
clearall();
delay(delaytime);
fillall();
delay(delaytime);
}
}
//Flashing LED in Fade manner
void fadeflash(int delaytime)
{
clearall();
int newdelay = delaytime / 5;
for(int fade = 0; fade <= 255; fade += 5)
{
for(int pin = 2; pin <= 19; pin++)
{
analogWrite(pin, fade);
}
delay(newdelay);
}
for(int fade = 255; fade >= 0; fade -= 5)
{
for(int pin = 2; pin <= 19; pin++)
{
analogWrite(pin, fade);
}
delay(newdelay);
}
}
//Alternatively Fade & Brightens
void fadealter(int delaytime)
{
clearall();
int newdelay = delaytime / 5;
for(int fade = 0; fade <= 255; fade += 5)
{
for(int i = 2; i <= 18; i+=2)
{
analogWrite(i, fade);
}
for (int j = 3; j <= 19; j += 2)
{
analogWrite(j, 255-fade);
}
delay(newdelay);
}

10
for(int fade = 255; fade >= 0; fade -= 5)
{
for(int i = 2; i <= 18; i+=2)
{
analogWrite(i, fade);
}
for (int j = 3; j <= 19; j += 2)
{
analogWrite(j, 255-fade);
}
delay(newdelay);
}
}
//Alternate Flash - Similar to Flash but alternate LEDs
void alternate(int delaytime)
{
for (int n = 1; n <= 5; n++)
{
clearall();
for (int i = 2; i <= 18; i += 2)
{
digitalWrite(i, HIGH);
}
delay(delaytime);
clearall();
for (int j = 3; j <= 19; j += 2)
{
digitalWrite(j, HIGH);
}
delay(delaytime);
}
}
//Putting all LEDs one by one in a stack
void stack(int delaytime)
{
int stack = 0;
while(stack < 18)
{
for(int pos = 2; pos <= (19 - stack); pos++)
{
clearall();
digitalWrite(pos, HIGH);
drawstack(stack);
delay(delaytime);
}
stack++;
}
}
//Subfunction of the stack function
void drawstack(int stack)
{

11
for(int n = 19; n > (19 - stack); n--)
{
if(n >= 2)
{
digitalWrite(n, HIGH);
}
}
}
//One LED chases another LED front and back
void chaser(int delaytime)
{
int div = 40;
int flashtime = delaytime / div;
int A = random(2,7);
int B = random(7,12);
int Av = 1;
int Bv = 1;
if(random(0,2))
{
Av *= -1;
}
if(random(0,2))
{
Bv *= -1;
}
for(int time = 1; time < 100; time++)
{
if(abs(A-B) == 1 && (Av*Bv) == -1)
{
for(int f = 1; f < round(div/4); f++)
{
clearall();
delay(flashtime);
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
delay(flashtime);
}
Av *= -1;
Bv *= -1;
A += Av;
B += Bv;
}
else
{
clearall();
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
A += Av;
B += Bv;
delay(delaytime);
}

12
if(A < 2)
{
A = 3;
Av *= -1;
}
if(B > 19)
{
B = 18;
Bv *= -1;
}
if(A >= B)
{
A = B-1;
}
}
}

Result:-
I will see all the led patterns running randomly this is because we have implemented random
function for pattern selection.

13
Ex.No:2
LED Pattern with Push Button Control using Arduino
Date :

Aim:-

To develop an application for LED Blink using Arduino

Components Required:-
 Mini push button switch
 5mm LED
 jumper wires
 Mini breadboard

Procedure:-
1.Insert LED into the Breadboard

Insert an LED into the breadboard with the Anode (positive leg) on the left and the Cathode (negative
leg on the right).
2.Insert a 220 ohm resistor

Insert a 220 Ohm Resistor so that one leg is inline with the LED's Cathode leg.Resistors are not
polarized, so orientation doesn't matter.This resistor will be used to limit the current going to our
LED.

14
3.Insert the button

Insert your push button so that one leg is in line with the other end of the resistor.Be sure to really
push down on the push button so that the bottom of the push button is flush with the breadboard (this
will feel like you're pushing too hard).
4.Connect pin 13 to the LED

Connect pin 13 to the anode of the LED.


5.Connect the resistor to ground

Connect the resistor to ground.

15
6.Connect the push button to pin 7

Connect the push button to pin 7.

Arduino Code 1: Push to turn on the LED

const int ledPin = 13;// We will use the internal LED


const int buttonPin = 7;// the pin our push button is on

void setup()
{
pinMode(ledPin,OUTPUT); // Set the LED Pin as an output
pinMode(buttonPin,INPUT_PULLUP); // Set the Tilt Switch as an input
}

void loop()
{
int digitalVal = digitalRead(buttonPin); // Take a reading

if(HIGH == digitalVal)
{
digitalWrite(ledPin,LOW); //Turn the LED off
}
else
{
digitalWrite(ledPin,HIGH);//Turn the LED on
}
}

When you run this code, the LED on Pin 13 will turn on when the button is held down. That is all.

Arduino Code 2: Toggle the LED


const unsigned int buttonPin = 7;
const unsigned int ledPin = 13;

int buttonState = 0;
int oldButtonState = LOW;
int ledState = LOW;

16
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
buttonState = digitalRead(buttonPin);

if (buttonState != oldButtonState &&


buttonState == HIGH)
{
ledState = (ledState == LOW ? HIGH : LOW);
digitalWrite(ledPin, ledState);
delay(50);
}
oldButtonState = buttonState;
}
This program will toggle on and off the LED every time you push the button.

Result:-
Thus the LED Pattern with Push Button Control using Arduino Successfully Completed.

17
Ex.No:3 LM35 Temperature Sensor to display temperature values using
Date : Arduino
Aim:-

To develop an application for LED Blink using Arduino

Components Required:-
 Arduino Uno - 1
 LM35 temperature sensor -1
 LCD 16×2 -1
 Breadboard -1
 Jumper wires - 2
 USB cable type A/B - 1

What is LM35 Temperature Sensor?


 LM35 sensor is a precision integrated-circuit temperature sensor, with an output voltage linearly
proportional to the Centigrade temperature.

 The LM35 device has an advantage over linear temperature sensors calibrated in Kelvin, as the
user is not required to subtract a large constant voltage from the output to obtain convenient
Centigrade scaling.
 The LM35 device does not require any external calibration or trimming to provide typical
accuracies of ± ¼ °C at room temperature and ± ¾ °C over a full −55°C to 150°C temperature
range. Lower cost is assured by trimming and calibration at the wafer level.
 The low output impedance, linear output, and precise inherent calibration of the LM35 device
make interfacing to readout or control circuitry especially easy.
 The device is used with single power supplies, or with plus and minus supplies.
 As the LM35 device draws only 60 μA from the supply, it has very low self-heating of less than
0.1°C in still air.
 The LM35 device is rated to operate over a −55°C to 150°C temperature range, while the
LM35C device is rated for a −40°C to 110°C range (−10° with improved accuracy).

LM35 Temperature Calculation:-


When you use a 5V Arduino and directly connect the sensor into an analog pin, you can use the
following formula to convert the 10-bit analog reading to a temperature:
Voltage at pin in milliVolts = (reading from ADC) * (5000/1024)
This formula converts the ADC number 0-1023 to 0-5000mV (= 5V).

18
When you use a 3.3V Arduino, you need to use the following formula:
Voltage at pin in milliVolts = (reading from ADC) * (3300/1024)
This formula converts the ADC number 0-1023 to 0-3300mV (= 3.3V)

Convert the millivolts into the temperature in degrees Celsius and Fahrenheit:
Centigrade temperature = (analog voltage in mV) / 10
Fahrenheit temperature=[(Centigrade temperature )*1.8]+32

Features of LM35:-
 Calibrated Directly in Celsius (Centigrade)

 Output proportional to °C
 Linear + 10-mV/°C Scale Factor
 Operates From 4 V to 30 V
 Less Than 60 μA Current Drain
 Low-Impedance Output, 0.1 Ω for 1 mA Load
 Low-Cost Due to Wafer-Level Trimming
 Accuracy 0.5°C (at 25°C)
 LM35 range temperature −55°C to 150°C
 Low Self-Heating, 0.08°C in Still Air
 Non-Linearity Only ±¼°C Typical
 Suitable for Remote Applications

LM35 Applications:-
 Temperature measurement in a specific environment

 Battery Temperature Monitoring


 Providing a circuit/component to thermal shutdown
 Temperature measurement for HVAC applications

19
Temperature Sensor LM35 Specifications:-

Supply Voltage +35V to −0.2V

Output Voltage +6V to −1.0V

Output Current 10mA

LM35 range temperature −55°C to 150°C

Accuracy 0.5°C (at 25°C)


±1°C (at −55°C to 150°C)

LM35 Temperature Sensor Circuit Diagram:-

LM35 Temperature Sensor Circuit Diagram

Here LM35’s out pin goes to A0.

20
LM35 Temperature Sensor Code:-
By clicking the button in the top right corner of the code field, you can copy the code. Copy and paste
it into Arduino IDE.

/*** www.arduinopoint.com ***/

/*** Arduino LM35 Temperature Sensor Project***/

// Define to which pin of the Arduino the output of the LM35 is connected:

#define sensorPin A0

void setup()
{

// Begin serial communication at a baud rate of 9600:

Serial.begin(9600);

void loop() {

// Get a reading from the temperature sensor:

int reading = analogRead(sensorPin);

// Convert the reading into voltage:

//Convert digital data into analog by multiplying by 5000 and dividing by 1024

float voltage = reading * (5000 / 1024.0);

// Convert the voltage into the temperature in degree Celsius:

float temperatureC = voltage / 10;

float temperatureF=(temperatureC*1.8)+32; // Converting to Fahrenheit

// Print the temperature in Celsius into the Serial Monitor:

Serial.print("Temperature in Celsius = ");

Serial.print(temperatureC);

21
Serial.print(" \xC2\xB0"); // shows degree symbol

Serial.println("C");

// Print the temperature in Celsius into the Serial Monitor:

Serial.print("Temperature in Fahrenheit = ");

Serial.print(temperatureF);

Serial.print(" \xC2\xB0"); // shows degree symbol

Serial.println("F");

Serial.print("\n");

delay(1000); // wait a second between readings

}
Output:-

Result:-
Thus the LM35 Temperature Sensor to display temperature values using Arduino
Successfully Completed and output is verified.

22
Ex.No:4 Forest fire detection end node using Raspberry Pi device and
Date : sensor

Aim:-

To develop an application for forest fire detection using Arduino.

Components Required:-

1 × Breadboard
1 × Arduino Uno
1 × Flame Sensor Module
1 × Buzzer
2 × Jumper
Fire Sensor:-

Buzzer:Circuit Diagram:-

23
Procedure:-

1. Give Connections as per the circuit diagram.

2. Open the Arduino IDE.

3. Write the code.

4. Set the Arduino board and port in Tools -> Board and Tools -> Port.

5. Compile the code by clicking verify in the upper left corner.

6. Upload the code by just clicking the right arrow present just next to verify.

7. As soon as the flame is detected , the alert will be given

Coding:

const int buzzerPin = 5;

const int flamePin = 2;

int Flame = HIGH;

void setup()

pinMode(buzzerPin, OUTPUT);

pinMode(flamePin, INPUT);

Serial.begin(9600);

void loop()

Flame = digitalRead(flamePin);

if (Flame== LOW){

Serial.println("Fire is Detected");

digitalWrite(buzzerPin, HIGH);

else

24
{

Serial.println("No Fire is Detected");

digitalWrite(buzzerPin, LOW);

Result :

Successfully develop the application for Forest fire detection end node using Raspberry Pi
device and sensor.

25
Ex.No:5
Application for Home Intrusion detection web application
Date :

Aim:-

To develop an application for home intrusion detection web application or IOT.

Componets Required:-
 Ultrasonic sensor
 Evive
Connection Wires
Procedure:-

 Once you have made the restricted area it’s to make the actual system that senses the
intrusion and aware the owner.
 For this purpose, the device that comes in our head first is the Ultrasonic System.
 To one out of the four sides, we are going to attach the Ultrasonic Sensor as shown in the
 figure.
 Once you have fixed it, it is time to make the owner aware of the intrusion.
 How are we going to do that?
 We will fix LEDs on all the four walls or on all the Ice Cream Sticks, using Hot Glue.
 The LEDs will be connected in a parallel connection.
 Connect all the Anodes ( Positive leg) of the Anode together using a Copper Wire.
 Similarly, connect all the cathode terminals of the LEDs, to one channel.
 You can also add a base of paper or foam.
 Thus, your assembly is completed all you need to do is complete its connection with evive
and upload the code.

Working:-

26
The specialty of the Ultrasonic Sensor is to detect the objects within a given range. Thus, as soon as
any human enters the restricted object, the sensor will detect this and send the signal to evive.
As soon as the signal triggers, all the LEDs on the walls lit up together. Not only the LEDs, but we
also have set up buzzer that will start buzzing as soon as the sensor detects the intrusion. Thus,
both LEDs and buzzer will be able to make the owner aware of the intrusion.

Code:-

#include<evive.h>

const unsigned int ultrasonic_threshould = 10;

const int buzz=46;

const int led =2;

const int trig = 4;

const int echo = 3;

// Variables for the duration and the distance

long duration;

int distance;

void setup() {

// put your setup code here, to run once:

Serial.begin(9600);

tft_init(INITR_GREENTAB);

tft.setRotation(1);

tft.fillScreen(1);

tft.setCursor(25,10);

tft.setTextSize(2);

tft.setTextColor(ST7735_WHITE,ST7735_BLACK);

tft.print("STEMpedia");

tft.setCursor(15,50);

tft.setTextSize(1.8);

tft.setTextColor(ST7735_GREEN,ST7735_BLACK);

tft.print("INTRUSION DETECTION ");

27
tft.setCursor(55,60);

tft.print("SYSTEM");

tft.setTextColor(ST7735_GREEN,ST7735_BLACK);

tft.setCursor(0,105);

tft.setTextSize(1.8);

tft.print("FOR MORE INFORMATION VISIT");

tft.setCursor(30,115);

tft.setTextColor(ST7735_WHITE,ST7735_BLACK);

tft.print("thestempedia.com");

pinMode(buzz,OUTPUT);

pinMode(led,OUTPUT);

pinMode(trig, OUTPUT); // Sets the trigPin as an Output

pinMode(echo, INPUT); // Sets the echoPin as an Input

void loop() {

// put your main code here, to run repeatedly:

distance = calculateDistance();

Serial.print("distance = ");

Serial.println(distance);

if(digitalRead(40)==HIGH)

if(distance > ultrasonic_threshould)

siren();

void siren()

28
{

for(int hz = 440; hz < 1000; hz+=25)

tone(buzz, hz, 50);

delay_ms();

// Whoop down

for(int hz = 1000; hz > 440; hz-=25)

tone(buzz, hz, 50);

delay_ms();

void delay_ms()

for(unsigned int k =0;k<5;k++)

digitalWrite(led,HIGH);

delay(1);

digitalWrite(led,LOW);

int calculateDistance()

digitalWrite(trig, LOW);

delayMicroseconds(2);

// Sets the trigPin on HIGH state for 10 micro seconds

digitalWrite(trig, HIGH);

29
delayMicroseconds(10);

digitalWrite(trig, LOW);

duration = pulseIn(echo, HIGH); // Reads the echoPin, returns the sound wave travel time in
microseconds

distance= duration*0.034/2;

return distance;

Output:-
Connect the LEDs and Ultrasonic Sensor as shown in the figure below:

Result :-

Successfully develop the application for Home intrusion detection in web application or IOT
completed and output is verified.

30
Ex.No:6 Application for Smart parking application using
Date :
python and Django for web application
Aim:

To develop an application for Smart parking system using python and Django for web application.

Components Required

Raspberry Pi 3 Model B
Raspberry Pi Camera Module
Ultrasonic Sensor – HC-SR04
SORACOM Air Global IoT SIM
Jumper Wires

Architecture of the system:

31
Coding:

# DetectPlates.py

import cv2

import numpy as np

import math

import Main

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)

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

cv2.destroyAllWindows()

if Main.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 Main.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 Main.showSteps == True: # show steps

#######################################################

print("step 2 - len(listOfPossibleCharsInScene) = " + str(

33
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, Main.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 Main.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 = []

34
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") # 13 with MCLRNF1 image

if Main.showSteps == True: # show steps

#######################################################

35
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]), Main.SCALAR_RED, 2)

cv2.line(imgContours, tuple(p2fRectPoints[1]), tuple(p2fRectPoints[2]), Main.SCALAR_RED, 2)

cv2.line(imgContours, tuple(p2fRectPoints[2]), tuple(p2fRectPoints[3]), Main.SCALAR_RED, 2)

cv2.line(imgContours, tuple(p2fRectPoints[3]), tuple(p2fRectPoints[0]), Main.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):

36
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 Main.showSteps == True: # show steps

###################################################

cv2.drawContours(imgContours, contours, i, Main.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

37
# end if

# end for

if Main.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

# DetectChars.py

import os

import cv2

import numpy as np

import math

import random

import Main

import Preprocess

import PossibleChar

# module level variables

##########################################################################

38
kNearest = cv2.ml.KNearest_create()

# constants for checkIfPossibleChar, this checks one possible char only (does not compare to another

char)

MIN_PIXEL_WIDTH = 2

MIN_PIXEL_HEIGHT = 8

MIN_ASPECT_RATIO = 0.25

MAX_ASPECT_RATIO = 1.0

MIN_PIXEL_AREA = 80

# constants for comparing two chars

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

# other constants

MIN_NUMBER_OF_MATCHING_CHARS = 3RESIZED_CHAR_IMAGE_WIDTH = 20

RESIZED_CHAR_IMAGE_HEIGHT = 30

MIN_CONTOUR_AREA = 100

#####################################################################################

##############

def loadKNNDataAndTrainKNN():

allContoursWithData = []

39
# declare empty lists,

validContoursWithData = []

# we will fill these shortly

try:

npaClassifications = np.loadtxt("classifications.txt", np.float32)

# read in training

classifications

except:

# if file could not be opened

print("error, unable to open classifications.txt, exiting program\n") # show error message

os.system("pause")

return False

# and return False

# end try

try:

npaFlattenedImages = np.loadtxt("flattened_images.txt", np.float32)

# read in training

images

except:

# if file could not be opened

print("error, unable to open flattened_images.txt, exiting program\n") # show error message

os.system("pause")

return False

40
# and return False

# end try

npaClassifications = npaClassifications.reshape((npaClassifications.size, 1))

# reshape numpy array

to 1d, necessary to pass to call to train

kNearest.setDefaultK(1)

# set default K to 1

kNearest.train(npaFlattenedImages, cv2.ml.ROW_SAMPLE, npaClassifications)

# train KNN

object

return True

# if we got here training was successful so return true

# end function

#####################################################################################

##############

def detectCharsInPlates(listOfPossiblePlates):

intPlateCounter = 0

imgContours = None

contours = []

if len(listOfPossiblePlates) == 0:

# if list of possible plates is empty

return listOfPossiblePlates

# return

41
# end if

# at this point we can be sure the list of possible plates has at least one plate

for possiblePlate in listOfPossiblePlates:

# for each possible plate, this is a big for loop that takes

up most of the functionpossiblePlate.imgGrayscale, possiblePlate.imgThresh =

Preprocess.preprocess(possiblePlate.imgPlate) # preprocess to get grayscale and threshold images

if Main.showSteps == True: # show steps

###################################################

cv2.imshow("5a", possiblePlate.imgPlate)

cv2.imshow("5b", possiblePlate.imgGrayscale)

cv2.imshow("5c", possiblePlate.imgThresh)

# end if # show steps

#####################################################################

# increase size of plate image for easier viewing and char detection

possiblePlate.imgThresh = cv2.resize(possiblePlate.imgThresh, (0, 0), fx = 1.6, fy = 1.6)

# threshold again to eliminate any gray areas

thresholdValue, possiblePlate.imgThresh = cv2.threshold(possiblePlate.imgThresh, 0.0, 255.0,

cv2.THRESH_BINARY | cv2.THRESH_OTSU)

if Main.showSteps == True: # show steps

###################################################

cv2.imshow("5d", possiblePlate.imgThresh)

# end if # show steps

#####################################################################

42
# find all possible chars in the plate,

# this function first finds all contours, then only includes contours that could be chars (without

comparison to other chars yet)

listOfPossibleCharsInPlate = findPossibleCharsInPlate(possiblePlate.imgGrayscale,

possiblePlate.imgThresh)

if Main.showSteps == True: # show steps

###################################################

height, width, numChannels = possiblePlate.imgPlate.shape

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

del contours[:]

# clear the contours list

for possibleChar in listOfPossibleCharsInPlate:

contours.append(possibleChar.contour)

# end for

cv2.drawContours(imgContours, contours, -1, Main.SCALAR_WHITE)

cv2.imshow("6", imgContours)

# end if # show steps

#####################################################################

# given a list of all possible chars, find groups of matching chars within the plate

listOfListsOfMatchingCharsInPlate = findListOfListsOfMatchingChars(listOfPossibleCharsInPlate)

if Main.showSteps == True: # show steps

###################################################

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

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

# end for

cv2.drawContours(imgContours, contours, -1, (intRandomBlue, intRandomGreen,

intRandomRed))

# end for

cv2.imshow("7", imgContours)

# end if # show steps

#####################################################################

if (len(listOfListsOfMatchingCharsInPlate) == 0):

# if no groups of matching chars

were found in the plate

if Main.showSteps == True: # show steps

###############################################

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

44
cv2.destroyWindow("10")

cv2.waitKey(0)

# end if # show steps

#################################################################

possiblePlate.strChars = ""

continue

# go back to top of for loop

# end if

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

# within each list of

matching chars

listOfListsOfMatchingCharsInPlate[i].sort(key = lambda matchingChar:

matchingChar.intCenterX)

# sort chars from left to right

listOfListsOfMatchingCharsInPlate[i] =

removeInnerOverlappingChars(listOfListsOfMatchingCharsInPlate[i])

# and remove inner

overlapping chars

# end for

if Main.showSteps == True: # show steps

###################################################

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

for listOfMatchingChars in listOfListsOfMatchingCharsInPlate:

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

# end for

cv2.drawContours(imgContours, contours, -1, (intRandomBlue, intRandomGreen,

intRandomRed))

# end for

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

#####################################################################

# within each possible plate, suppose the longest list of potential matching chars is the actual

list of chars

intLenOfLongestListOfChars = 0

intIndexOfLongestListOfChars = 0

# loop through all the vectors of matching chars, get the index of the one with the most chars

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

if len(listOfListsOfMatchingCharsInPlate[i]) > intLenOfLongestListOfChars:

intLenOfLongestListOfChars = len(listOfListsOfMatchingCharsInPlate[i])

intIndexOfLongestListOfChars = i

# end if

# end for

46
# suppose that the longest list of matching chars within the plate is the actual list of chars

longestListOfMatchingCharsInPlate =

listOfListsOfMatchingCharsInPlate[intIndexOfLongestListOfChars]

if Main.showSteps == True: # show steps

###################################################

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

del contours[:]

for matchingChar in longestListOfMatchingCharsInPlate:

contours.append(matchingChar.contour)

# end for

cv2.drawContours(imgContours, contours, -1, Main.SCALAR_WHITE)

cv2.imshow("9", imgContours)

# end if # show steps

#####################################################################

possiblePlate.strChars = recognizeCharsInPlate(possiblePlate.imgThresh,

longestListOfMatchingCharsInPlate)

if Main.showSteps == True: # show steps

###################################################

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)

47
# end if # show steps

#####################################################################

# end of big for loop that takes up most of the function

if Main.showSteps == True:

print("\nchar detection complete, click on any image and press a key to continue . . .\n")

cv2.waitKey(0)

# end if

return listOfPossiblePlates

# end
function##################################################################################
###

##############

def findPossibleCharsInPlate(imgGrayscale, imgThresh):

listOfPossibleChars = []

# this will be the return value

contours = []

imgThreshCopy = imgThresh.copy()

# find all contours in plate

imgContours, contours, npaHierarchy = cv2.findContours(imgThreshCopy, cv2.RETR_LIST,

cv2.CHAIN_APPROX_SIMPLE)

for contour in contours:

# for each contour

possibleChar = PossibleChar.PossibleChar(contour)

if checkIfPossibleChar(possibleChar):

48
# if contour is a possible char, note this does not

compare to other chars (yet) . . .

listOfPossibleChars.append(possibleChar)

# add to list of possible chars

# end if

# end if

return listOfPossibleChars

# end function

#####################################################################################

##############

def checkIfPossibleChar(possibleChar):

# this function is a 'first pass' that does a rough check on a contour to see if it could be a char,

# note that we are not (yet) comparing the char to other chars to look for a group

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

# end if

# end function

49
#####################################################################################

##############

def findListOfListsOfMatchingChars(listOfPossibleChars):

# with this function, we start off with all the possible chars in one big list

# the purpose of this function is to re-arrange the one big list of chars into a list of lists of

matching chars,

# note that chars that are not found to be in a group of matches do not need to be considered

further

listOfListsOfMatchingChars = []

# this will be the return value

for possibleChar in listOfPossibleChars:

# for each possible char in the one big list of

chars

listOfMatchingChars = findListOfMatchingChars(possibleChar, listOfPossibleChars)

# find all

chars in the big list that match the current char

listOfMatchingChars.append(possibleChar)

# also add the current char to current possible

list of matching charsif len(listOfMatchingChars) < MIN_NUMBER_OF_MATCHING_CHARS: # if current


possible

list of matching chars is not long enough to constitute a possible plate

continue

# jump back to the top of the for loop and try again with next char, note

that it's not necessary

50
possible plate

# end if

# to save the list in any way since it did not have enough chars to be a

# if we get here, the current list passed test as a "group" or "cluster" of

matching chars

listOfListsOfMatchingChars.append(listOfMatchingChars)

# so add to our list of lists of

matching chars

listOfPossibleCharsWithCurrentMatchesRemoved = []

those same chars twice,

the original big list

# remove the current list of matching chars from the big list so we don't use

# make sure to make a new big list for this since we don't want to change

listOfPossibleCharsWithCurrentMatchesRemoved = list(set(listOfPossibleChars) -

set(listOfMatchingChars))

recursiveListOfListsOfMatchingChars =

findListOfListsOfMatchingChars(listOfPossibleCharsWithCurrentMatchesRemoved)

# recursive call

for recursiveListOfMatchingChars in recursiveListOfListsOfMatchingChars:

# for each list of

matching chars found by recursive call

listOfListsOfMatchingChars.append(recursiveListOfMatchingChars)

# add to our original

51
list of lists of matching chars

# end for

break

# exit for

# end for

return listOfListsOfMatchingChars

# end function

#####################################################################################

##############

def findListOfMatchingChars(possibleChar, listOfChars):

# the purpose of this function is, given a possible char and a big list of possible chars,

# find all chars in the big list that are a match for the single possible char, and return those

matching chars as a list

listOfMatchingChars = []

# this will be the return value

for possibleMatchingChar in listOfChars:

# for each char in big list

if possibleMatchingChar == possibleChar: # if the char we attempting to find matches for is the

exact same char as the char in the big list we are currently checking

# then we should not include it in the list of matches b/c that would end

up double including the current char

continue

# so do not add to list of matches and jump back to top of for loop

52
# end if

# compute stuff to see if chars are a match

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)

# check if chars match

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)

# if the chars are a match, add the

current char to list of matching chars

# end if

# end for

return listOfMatchingChars

# return result

53
# end function

#####################################################################################

##############

# use Pythagorean theorem to calculate distance between two chars

def distanceBetweenChars(firstChar, secondChar):

intX = abs(firstChar.intCenterX - secondChar.intCenterX)

intY = abs(firstChar.intCenterY - secondChar.intCenterY)

return math.sqrt((intX ** 2) + (intY ** 2))

# end function

#####################################################################################

##############

# use basic trigonometry (SOH CAH TOA) to calculate angle between chars

def angleBetweenChars(firstChar, secondChar):

fltAdj = float(abs(firstChar.intCenterX - secondChar.intCenterX))

fltOpp = float(abs(firstChar.intCenterY - secondChar.intCenterY))

if fltAdj != 0.0:

# check to make sure we do not divide by zero if the center X positions

are equal, float division by zero will cause a crash in Python

fltAngleInRad = math.atan(fltOpp / fltAdj)

# if adjacent is not zero, calculate angle

else:

fltAngleInRad = 1.5708

# if adjacent is zero, use this as the angle, this is to be

54
consistent with the C++ version of this program

# end if

fltAngleInDeg = fltAngleInRad * (180.0 / math.pi)

# calculate angle in degrees

return fltAngleInDeg

# end function

#####################################################################################

##############

# if we have two chars overlapping or to close to each other to possibly be separate chars, remove the

inner (smaller) char,# this is to prevent including the same char twice if two contours are found for the same
char,

# for example for the letter 'O' both the inner ring and the outer ring may be found as contours, but we

should only include the char once

def removeInnerOverlappingChars(listOfMatchingChars):

listOfMatchingCharsWithInnerCharRemoved = list(listOfMatchingChars)

# this will be the

return value

for currentChar in listOfMatchingChars:

for otherChar in listOfMatchingChars:

if currentChar != otherChar:

# if current char and other char are not the same char . . .

# if current char and other char have center points at

almost the same location . . .

if distanceBetweenChars(currentChar, otherChar) < (currentChar.fltDiagonalSize *

55
MIN_DIAG_SIZE_MULTIPLE_AWAY):

# if we get in here we have found overlapping chars

# next we identify which char is smaller, then if that char was not already removed on

a previous pass, remove it

if currentChar.intBoundingRectArea < otherChar.intBoundingRectArea:

# if current

char is smaller than other char

if currentChar in listOfMatchingCharsWithInnerCharRemoved:

# if current char

was not already removed on a previous pass . . .

listOfMatchingCharsWithInnerCharRemoved.remove(currentChar)

# then remove

current char

char

# end if

else:

# else if other char is smaller than current

if otherChar in listOfMatchingCharsWithInnerCharRemoved:

# if other char was

not already removed on a previous pass . . .

listOfMatchingCharsWithInnerCharRemoved.remove(otherChar)

# then remove

other char

56
# end if

# end if

# end if

# end if

# end for

# end for

return listOfMatchingCharsWithInnerCharRemoved

# end function

#####################################################################################

##############

# this is where we apply the actual char recognition

def recognizeCharsInPlate(imgThresh, listOfMatchingChars):

strChars = ""

# this will be the return value, the chars in the lic plate

height, width = imgThresh.shape

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

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

# sort chars

from left to right

cv2.cvtColor(imgThresh, cv2.COLOR_GRAY2BGR, imgThreshColor)

# make color

version of threshold image so we can draw contours in color on it

for currentChar in listOfMatchingChars:

57
# for each char in plate

pt1 = (currentChar.intBoundingRectX, currentChar.intBoundingRectY)pt2 = ((currentChar.intBoundingRectX


+ currentChar.intBoundingRectWidth),

(currentChar.intBoundingRectY + currentChar.intBoundingRectHeight))

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

# draw green box

around the char

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

# resize image, this is necessary for char recognition

npaROIResized = imgROIResized.reshape((1, RESIZED_CHAR_IMAGE_WIDTH *

RESIZED_CHAR_IMAGE_HEIGHT))

# flatten image into 1d numpy array

npaROIResized = np.float32(npaROIResized)

# convert from 1d numpy array of ints to 1d

numpy array of floats

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

# finally

we can call findNearest !!!

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

# get character from results

strChars = strChars + strCurrentChar

# append current char to full string

# end for

if Main.showSteps == True: # show steps

#######################################################

cv2.imshow("10", imgThreshColor)

# end if # show steps

#########################################################################

return strChars

# 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

59
fltPlateCenterY = (listOfMatchingChars[0].intCenterY +

listOfMatchingChars[len(listOfMatchingChars) - 1].intCenterY) / 2.0

ptPlateCenter = fltPlateCenterX, fltPlateCenterY

# calculate plate width and heightintPlateWidth = 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 )

60
# 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

Main.py

import cv2

import numpy as np

import os

import DetectChars

import DetectPlates

import PossiblePlate

# module level variables

##########################################################################SCALAR_BLAC
K = (0.0, 0.0, 0.0)

61
SCALAR_WHITE = (255.0, 255.0, 255.0)

SCALAR_YELLOW = (0.0, 255.0, 255.0)

SCALAR_GREEN = (0.0, 255.0, 0.0)

SCALAR_RED = (0.0, 0.0, 255.0)

showSteps = False

#####################################################################################

##############

def main():

blnKNNTrainingSuccessful = DetectChars.loadKNNDataAndTrainKNN()

# attempt KNN

training

if blnKNNTrainingSuccessful == False:

# if KNN training was not successful

print("\nerror: KNN traning was not successful\n") # show error message

return

# and exit program

# end if

imgOriginalScene = cv2.imread("LicPlateImages/1.png")

# open image

if imgOriginalScene is None:

# if image was not read successfully

print("\nerror: image not read from file \n\n") # print error message to std out

os.system("pause")

62
# pause so user can see error message

return

# and exit program

# end if

listOfPossiblePlates = DetectPlates.detectPlatesInScene(imgOriginalScene)

# detect plates

listOfPossiblePlates = DetectChars.detectCharsInPlates(listOfPossiblePlates)

# detect chars in

plates

cv2.imshow("imgOriginalScene", imgOriginalScene)

# show scene image

if len(listOfPossiblePlates) == 0:

# if no plates were found

print("\nno license plates were detected\n") # inform user no plates were found

else:

# else

# if we get in here list of possible plates has at leat one plate

# sort the list of possible plates in DESCENDING order (most number of chars to least number

of chars)

listOfPossiblePlates.sort(key = lambda possiblePlate: len(possiblePlate.strChars), reverse = True)

# suppose the plate with the most recognized chars (the first plate in sorted by string length

descending order) is the actual plate

licPlate = listOfPossiblePlates[0]

63
cv2.imshow("imgPlate", licPlate.imgPlate)

# show crop of plate and threshold of plate

cv2.imshow("imgThresh", licPlate.imgThresh)

if len(licPlate.strChars) == 0:

# if no chars were found in the plate

print("\nno characters were detected\n\n") # show message

return

# and exit program

# end if

drawRedRectangleAroundPlate(imgOriginalScene, licPlate)

# draw red rectangle around

plateout

print("\nlicense plate read from image = " + licPlate.strChars + "\n") # write license plate text to std

print("-

-")

writeLicensePlateCharsOnImage(imgOriginalScene, licPlate)

# write license plate text on the

image

cv2.imshow("imgOriginalScene", imgOriginalScene)

# re-show scene image

cv2.imwrite("imgOriginalScene.png", imgOriginalScene)

# write image out to file

# end if else

64
cv2.waitKey(0)

# hold windows open until user presses a key

return

# end main

#####################################################################################

##############

def drawRedRectangleAroundPlate(imgOriginalScene, licPlate):

p2fRectPoints = cv2.boxPoints(licPlate.rrLocationOfPlateInScene)

# get 4 vertices of rotated

rect

cv2.line(imgOriginalScene, tuple(p2fRectPoints[0]), tuple(p2fRectPoints[1]), SCALAR_RED, 2)

# draw 4 red lines

cv2.line(imgOriginalScene, tuple(p2fRectPoints[1]), tuple(p2fRectPoints[2]), SCALAR_RED, 2)

cv2.line(imgOriginalScene, tuple(p2fRectPoints[2]), tuple(p2fRectPoints[3]), SCALAR_RED, 2)

cv2.line(imgOriginalScene, tuple(p2fRectPoints[3]), tuple(p2fRectPoints[0]), SCALAR_RED, 2)

# end function

#####################################################################################

##############

def writeLicensePlateCharsOnImage(imgOriginalScene, licPlate):

ptCenterOfTextAreaX = 0

# this will be the center of the area the text will be written

to

ptCenterOfTextAreaY = 0

65
ptLowerLeftTextOriginX = 0

# this will be the bottom left of the area that the text will

be written to

ptLowerLeftTextOriginY = 0

sceneHeight, sceneWidth, sceneNumChannels = imgOriginalScene.shape

plateHeight, plateWidth, plateNumChannels = licPlate.imgPlate.shape

intFontFace = cv2.FONT_HERSHEY_SIMPLEX

# choose a plain jane font

fltFontScale = float(plateHeight) / 30.0

# base font scale on height of plate area

intFontThickness = int(round(fltFontScale * 1.5))

# base font thickness on font scale

textSize, baseline = cv2.getTextSize(licPlate.strChars, intFontFace, fltFontScale, intFontThickness)

# call getTextSize

# unpack roatated rect into center point, width and height, and angle

( (intPlateCenterX, intPlateCenterY), (intPlateWidth, intPlateHeight), fltCorrectionAngleInDeg ) =

licPlate.rrLocationOfPlateInSceneintPlateCenterX = int(intPlateCenterX)

# make sure center is an integer

intPlateCenterY = int(intPlateCenterY)

ptCenterOfTextAreaX = int(intPlateCenterX)

# the horizontal location of the text area is the same

as the plate

if intPlateCenterY < (sceneHeight * 0.75):

66
# if the license plate is in the

upper 3/4 of the image

ptCenterOfTextAreaY = int(round(intPlateCenterY)) + int(round(plateHeight * 1.6))

# write the

chars in below the plate

else:

# else if the license plate is in the lower 1/4

of the image

ptCenterOfTextAreaY = int(round(intPlateCenterY)) - int(round(plateHeight * 1.6))

# write the

chars in above the plate

# end if

textSizeWidth, textSizeHeight = textSize

# unpack text size width and height

ptLowerLeftTextOriginX = int(ptCenterOfTextAreaX - (textSizeWidth / 2))

# calculate the

lower left origin of the text area

ptLowerLeftTextOriginY = int(ptCenterOfTextAreaY + (textSizeHeight / 2))

# based on the text

area center, width, and height

# write the text on the image

cv2.putText(imgOriginalScene, licPlate.strChars, (ptLowerLeftTextOriginX,

ptLowerLeftTextOriginY), intFontFace, fltFontScale, SCALAR_YELLOW, intFontThickness)

67
# end function

#####################################################################################

##############

if name == " main ":

main()

# 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# Preprocess.py

import cv2

import numpy as np

68
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

69
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

# PossibleChar.py

import cv2

import numpy as np

import math

#####################################################################################

##############

70
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

71
Output:-

Result: -

Thus the web application was developed for Smart parking system using python

72

You might also like