Upload 14 files
Browse files- .idea/.gitignore +3 -0
- .idea/inspectionProfiles/profiles_settings.xml +6 -0
- .idea/misc.xml +4 -0
- .idea/modules.xml +8 -0
- .idea/traffic_signs_classification.iml +10 -0
- README.md +15 -12
- app_images/road_sign.jpg +0 -0
- keras_model/keras_metadata.pb +3 -0
- keras_model/saved_model.pb +3 -0
- keras_model/variables/variables.data-00000-of-00001 +0 -0
- keras_model/variables/variables.index +0 -0
- requirements.txt +7 -0
- streamlit_app.py +121 -0
- traffic_signs_classification_lenet5.ipynb +0 -0
.idea/.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Default ignored files
|
| 2 |
+
/shelf/
|
| 3 |
+
/workspace.xml
|
.idea/inspectionProfiles/profiles_settings.xml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<component name="InspectionProjectProfileManager">
|
| 2 |
+
<settings>
|
| 3 |
+
<option name="USE_PROJECT_PROFILE" value="false" />
|
| 4 |
+
<version value="1.0" />
|
| 5 |
+
</settings>
|
| 6 |
+
</component>
|
.idea/misc.xml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<project version="4">
|
| 3 |
+
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (traffic_signs_classification)" project-jdk-type="Python SDK" />
|
| 4 |
+
</project>
|
.idea/modules.xml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<project version="4">
|
| 3 |
+
<component name="ProjectModuleManager">
|
| 4 |
+
<modules>
|
| 5 |
+
<module fileurl="file://$PROJECT_DIR$/.idea/traffic_signs_classification.iml" filepath="$PROJECT_DIR$/.idea/traffic_signs_classification.iml" />
|
| 6 |
+
</modules>
|
| 7 |
+
</component>
|
| 8 |
+
</project>
|
.idea/traffic_signs_classification.iml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<module type="PYTHON_MODULE" version="4">
|
| 3 |
+
<component name="NewModuleRootManager">
|
| 4 |
+
<content url="file://$MODULE_DIR$">
|
| 5 |
+
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
| 6 |
+
</content>
|
| 7 |
+
<orderEntry type="inheritedJdk" />
|
| 8 |
+
<orderEntry type="sourceFolder" forTests="false" />
|
| 9 |
+
</component>
|
| 10 |
+
</module>
|
README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# traffic_signs_classification
|
| 2 |
+
|
| 3 |
+
The purpose of this project is to train an implementation of the LeNet-5 Convolutional Neural Network for the
|
| 4 |
+
classification of traffic signs provided by the user. The model was trained and tested on about 40.000 real photos of 43
|
| 5 |
+
types of german traffic signs. Data was taken from The German Traffic Sign Recognition Benchmark (GTSRB): https://benchmark.ini.rub.de/gtsrb_dataset.html
|
| 6 |
+
|
| 7 |
+
Notebook with built and trained model: **traffic_signs_classification_lenet5.ipynb**
|
| 8 |
+
|
| 9 |
+
Folder with saved model: **keras_model**
|
| 10 |
+
|
| 11 |
+
Streamlit application for testing the model: **streamlit_app.py**
|
| 12 |
+
|
| 13 |
+
Article: https://towardsdatascience.com/classification-of-traffic-signs-with-lenet-5-cnn-cb861289bd62
|
| 14 |
+
|
| 15 |
+
Link to Streamlit app: https://share.streamlit.io/andriigoz/traffic_signs_classification
|
app_images/road_sign.jpg
ADDED
|
keras_model/keras_metadata.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:53a3f046cf6060be29b41e6b77c656851ed5d3b5ce93e6672f4f238592b1364b
|
| 3 |
+
size 19323
|
keras_model/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:461ab68ffe048c5c8157e7dd7c9af66ccc02bb60024bfe01d6f77ee631760df5
|
| 3 |
+
size 169181
|
keras_model/variables/variables.data-00000-of-00001
ADDED
|
Binary file (853 kB). View file
|
|
|
keras_model/variables/variables.index
ADDED
|
Binary file (2.7 kB). View file
|
|
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
keras==2.7.0
|
| 2 |
+
numpy==1.21.0
|
| 3 |
+
opencv-python-headless
|
| 4 |
+
Pillow==9.0.0
|
| 5 |
+
streamlit==1.4.0
|
| 6 |
+
tensorflow==2.7.0
|
| 7 |
+
click==8
|
streamlit_app.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import streamlit as st
|
| 3 |
+
import cv2 as cv
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from keras.models import load_model
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
# Label traffic signs
|
| 9 |
+
labels_dict = {
|
| 10 |
+
0: '274. Speed limit (20km/h)',
|
| 11 |
+
1: '274. Speed limit (30km/h)',
|
| 12 |
+
2: '274. Speed limit (50km/h)',
|
| 13 |
+
3: '274. Speed limit (60km/h)',
|
| 14 |
+
4: '274. Speed limit (70km/h)',
|
| 15 |
+
5: '274. Speed limit (80km/h)',
|
| 16 |
+
6: '278. End of speed limit (80km/h)',
|
| 17 |
+
7: '274. Speed limit (100km/h)',
|
| 18 |
+
8: '274. Speed limit (120km/h)',
|
| 19 |
+
9: '276. No passing',
|
| 20 |
+
10: '277. No passing vehicle over 3.5 tons',
|
| 21 |
+
11: '301. Right-of-way at intersection',
|
| 22 |
+
12: '306. Priority road',
|
| 23 |
+
13: '205. Yield',
|
| 24 |
+
14: '206. Stop',
|
| 25 |
+
15: '250. No vehicles',
|
| 26 |
+
16: '253. Vehicle > 3.5 tons prohibited',
|
| 27 |
+
17: '267. No entry',
|
| 28 |
+
18: '101. General caution',
|
| 29 |
+
19: '104. Dangerous curve left',
|
| 30 |
+
20: '103. Dangerous curve right',
|
| 31 |
+
21: '105-10. Double curve',
|
| 32 |
+
22: '112. Bumpy road',
|
| 33 |
+
23: '114. Slippery road',
|
| 34 |
+
24: '121. Road narrows on the right',
|
| 35 |
+
25: '123. Road work',
|
| 36 |
+
26: '131. Traffic signals',
|
| 37 |
+
27: '133. Pedestrians',
|
| 38 |
+
28: '136. Children crossing',
|
| 39 |
+
29: '138. Bicycles crossing',
|
| 40 |
+
30: '101-51. Beware of ice/snow',
|
| 41 |
+
31: '142. Wild animals crossing',
|
| 42 |
+
32: '282. End speed + passing limits',
|
| 43 |
+
33: '209-20. Turn right ahead',
|
| 44 |
+
34: '209-10. Turn left ahead',
|
| 45 |
+
35: '209-30. Ahead only',
|
| 46 |
+
36: '214-20. Go straight or right',
|
| 47 |
+
37: '214-10. Go straight or left',
|
| 48 |
+
38: '222-20. Keep right',
|
| 49 |
+
39: '222-10. Keep left',
|
| 50 |
+
40: '215. Roundabout mandatory',
|
| 51 |
+
41: '280. End of no passing',
|
| 52 |
+
42: '281. End no passing vehicle > 3.5 tons'
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@st.cache
|
| 57 |
+
def sign_predict(image):
|
| 58 |
+
model = load_model('keras_model\saved_model.pb')
|
| 59 |
+
image = np.array(image, dtype=np.float32)
|
| 60 |
+
image = image/255
|
| 61 |
+
image = np.reshape(image, (1, 32, 32))
|
| 62 |
+
x = image.astype(np.float32)
|
| 63 |
+
prediction = model.predict(x)
|
| 64 |
+
prediction_max = np.argmax(prediction)
|
| 65 |
+
prediction_label = labels_dict[prediction_max]
|
| 66 |
+
confidence = np.max(prediction)
|
| 67 |
+
return prediction_label, confidence
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def main():
|
| 71 |
+
# Set page config and markdowns
|
| 72 |
+
st.set_page_config(page_title='Traffic Signs Classifier', page_icon=':car:')
|
| 73 |
+
st.title('Traffic Signs Classifier')
|
| 74 |
+
st.markdown("""
|
| 75 |
+
This application classifies traffic signs. Upload any photo of a traffic sign
|
| 76 |
+
and receive its name out of 43 present classes. For getting the correct prediction,
|
| 77 |
+
try to upload a square picture containing only the sign.
|
| 78 |
+
""")
|
| 79 |
+
with st.expander("See list of classes"):
|
| 80 |
+
st.write(list(labels_dict.values()))
|
| 81 |
+
st.image('./app_images/road_sign.jpg', use_column_width=True)
|
| 82 |
+
image_usr = st.file_uploader('Upload a photo of traffic sign here', type=['jpg', 'jpeg', 'png'])
|
| 83 |
+
|
| 84 |
+
if image_usr is not None:
|
| 85 |
+
col1, col2 = st.columns(2)
|
| 86 |
+
col1.markdown('#### Your picture')
|
| 87 |
+
col2.markdown('#### Your picture 32x32 gray')
|
| 88 |
+
image = Image.open(image_usr)
|
| 89 |
+
with col1:
|
| 90 |
+
st.image(image, use_column_width=True)
|
| 91 |
+
|
| 92 |
+
image_np = np.array(image.convert('RGB'))
|
| 93 |
+
image_col = cv.cvtColor(image_np, 1)
|
| 94 |
+
image_gray = cv.cvtColor(image_col, cv.COLOR_BGR2GRAY)
|
| 95 |
+
image_32 = cv.resize(image_gray, (32, 32))
|
| 96 |
+
with col2:
|
| 97 |
+
st.image(image_32, use_column_width=True)
|
| 98 |
+
|
| 99 |
+
# Make prediction
|
| 100 |
+
prediction_label, confidence = sign_predict(image_32)
|
| 101 |
+
|
| 102 |
+
st.write('##### Prediction:', prediction_label)
|
| 103 |
+
st.write('##### Confidence:', str(confidence))
|
| 104 |
+
st.markdown('***')
|
| 105 |
+
|
| 106 |
+
# Markdowns
|
| 107 |
+
st.subheader('About this app')
|
| 108 |
+
st.markdown("""
|
| 109 |
+
The app uses an implementation of LeNet-5 Convolutional Neural Network.
|
| 110 |
+
The model was trained and tested on about 40.000 real photos of 43 types of german traffic signs.
|
| 111 |
+
|
| 112 |
+
Data was taken from The German Traffic Sign Recognition Benchmark (GTSRB):
|
| 113 |
+
https://benchmark.ini.rub.de/gtsrb_dataset.html
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
Author: Prajwal Thawari
|
| 117 |
+
""")
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
if __name__ == '__main__':
|
| 121 |
+
main()
|
traffic_signs_classification_lenet5.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|