iamisha commited on
Commit
dd47838
·
verified ·
1 Parent(s): a4a0093

Upload 6 files

Browse files
Files changed (7) hide show
  1. .gitattributes +1 -0
  2. app.py +282 -0
  3. best.pt +3 -0
  4. best24.pt +3 -0
  5. demo0.mp4 +3 -0
  6. dockerfile +34 -0
  7. requirements.txt +0 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ demo0.mp4 filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import tempfile
3
+ import streamlit as st
4
+ from ultralytics import YOLO, solutions
5
+ import os
6
+ import time
7
+ from collections import defaultdict
8
+
9
+
10
+ def main():
11
+ st.title('Licence Plate Recognition and Vehicle Counting')
12
+
13
+ st.sidebar.title('Settings')
14
+ st.markdown(
15
+ """
16
+ <style>
17
+ [data-testid="stSidebar"][aria-expanded="true"] > div:first-child{width: 350px;}
18
+ [data-testid="stSidebar"][aria-expanded="false"] > div:first-child{width: 350px; margin-left: -400px;}
19
+ </style>
20
+ """,
21
+ unsafe_allow_html=True,
22
+ )
23
+
24
+ enable_GPU = st.sidebar.checkbox('Enable GPU')
25
+ custom_classes = st.sidebar.checkbox('Use Custom Classes')
26
+ assigned_class_id = []
27
+
28
+ names = ['car', 'motorcycle', 'bus', 'train', 'truck', 'bike']
29
+ if custom_classes:
30
+ assigned_class = st.sidebar.multiselect('Select The Custom Classes', list(names), default='bike')
31
+ for each in assigned_class:
32
+ assigned_class_id.append(names.index(each))
33
+
34
+ media_type = st.sidebar.radio("Choose media type", ('Video', 'Image'))
35
+
36
+ # Load the YOLO models
37
+ license_plate_model = YOLO('best24.pt')
38
+ character_model = YOLO('best.pt') # replace with your character segmentation model
39
+
40
+ def process_image(image):
41
+ results = license_plate_model.predict(image)
42
+ return results
43
+
44
+ if media_type == 'Video':
45
+ video_file_buffer = st.sidebar.file_uploader("Upload a video", type=["mp4", "mov", 'avi', 'asf', 'm4v'])
46
+ DEMO_VIDEO = 'demo0.mp4'
47
+ tffile = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
48
+
49
+ if not video_file_buffer:
50
+ if os.path.exists(DEMO_VIDEO):
51
+ tffile.name = DEMO_VIDEO
52
+ vid = cv2.VideoCapture(DEMO_VIDEO)
53
+ else:
54
+ st.error(f"Demo video file not found: {DEMO_VIDEO}. Please upload a video.")
55
+ return
56
+ else:
57
+ tffile.write(video_file_buffer.read())
58
+ tffile.close() # Ensure the file is closed before using it
59
+ vid = cv2.VideoCapture(tffile.name)
60
+
61
+ dem_vid = open(tffile.name, 'rb')
62
+ demo_bytes = dem_vid.read()
63
+ dem_vid.close() # Ensure the file is closed after reading
64
+
65
+ stframe = st.empty()
66
+ st.info('Input Video')
67
+ # st.video(demo_bytes)
68
+ st.sidebar.markdown('---')
69
+
70
+ confidence = st.sidebar.slider('Confidence', min_value=0.0, max_value=1.0, value=0.25)
71
+ st.sidebar.markdown('---')
72
+
73
+ cap = cv2.VideoCapture(tffile.name)
74
+ if not cap.isOpened():
75
+ st.error(f"Error reading video file: {tffile.name}")
76
+ return
77
+
78
+ w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
79
+
80
+ output_width = w
81
+ output_height = h
82
+
83
+ # Radio button to choose between vertical and horizontal line
84
+ line_orientation = st.sidebar.radio('Line Orientation', ('Horizontal', 'Vertical'))
85
+
86
+ # Slider for dynamic shift amount
87
+ if line_orientation == 'Horizontal':
88
+ vertical_shift = st.sidebar.slider('Shift Amount (Vertical Shift)', min_value=0, max_value=h, value=250, step=50)
89
+ line_points = [(0, vertical_shift), (w, vertical_shift)]
90
+ else:
91
+ horizontal_shift = st.sidebar.slider('Shift Amount (Horizontal Shift)', min_value=0, max_value=w, value=200, step=50)
92
+ line_points = [(horizontal_shift, 0), (horizontal_shift, h)]
93
+
94
+ st.sidebar.markdown('---')
95
+
96
+ # Display the initial frame with the line
97
+ ret, frame = cap.read()
98
+ if ret:
99
+ cv2.line(frame, line_points[0], line_points[1], (255, 0, 0), 2)
100
+ st.image(frame, channels="BGR")
101
+
102
+ kpi1, kpi2, kpi3 = st.columns(3)
103
+
104
+ with kpi1:
105
+ st.markdown("**Frame Rate**")
106
+ kpi1_text = st.markdown(fps)
107
+
108
+ with kpi2:
109
+ st.markdown("**Height**")
110
+ kpi2_text = st.markdown(h)
111
+
112
+ with kpi3:
113
+ st.markdown("**Width**")
114
+ kpi3_text = st.markdown(w)
115
+
116
+ if st.button('Process Video'):
117
+ classes_to_count = [0,1,2]
118
+
119
+ output_video_path = tempfile.NamedTemporaryFile(delete=False, suffix='.avi').name
120
+ video_writer = cv2.VideoWriter(output_video_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (output_width, output_height))
121
+
122
+ # Init Object Counter
123
+ counter = solutions.ObjectCounter(
124
+ view_img=False,
125
+ reg_pts=line_points,
126
+ names=license_plate_model.names,
127
+ draw_tracks=True,
128
+ line_thickness=2,
129
+ line_dist_thresh=50
130
+ )
131
+
132
+ while cap.isOpened():
133
+ success, im0 = cap.read()
134
+ if not success:
135
+ print("Video frame is empty or video processing has been successfully completed.")
136
+ break
137
+ tracks = license_plate_model.track(im0, persist=True, show=False, classes=classes_to_count)
138
+
139
+ im0 = counter.start_counting(im0, tracks)
140
+ video_writer.write(im0)
141
+
142
+ cap.release()
143
+ video_writer.release()
144
+ cv2.destroyAllWindows()
145
+
146
+ # Provide a download link for the processed video
147
+ if os.path.exists(output_video_path):
148
+ with open(output_video_path, 'rb') as f:
149
+ st.download_button(
150
+ label="Download Processed Video",
151
+ data=f,
152
+ file_name="processed_video.avi",
153
+ mime="video/avi"
154
+ )
155
+
156
+ else:
157
+ st.error(f"Processed video file not found: {output_video_path}")
158
+
159
+ time.sleep(1) # Wait for a second before attempting to delete the file
160
+
161
+ def is_file_in_use(filepath):
162
+ try:
163
+ os.rename(filepath, filepath)
164
+ return False
165
+ except OSError:
166
+ return True
167
+
168
+ if not is_file_in_use(tffile.name):
169
+ try:
170
+ os.remove(tffile.name)
171
+ except Exception as e:
172
+ st.write(f"Error deleting temporary video file: {e}")
173
+
174
+ if not is_file_in_use(output_video_path):
175
+ try:
176
+ os.remove(output_video_path)
177
+ except Exception as e:
178
+ st.write(f"Error deleting output video file: {e}")
179
+
180
+ else:
181
+ image_file_buffer = st.sidebar.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
182
+ if image_file_buffer is not None:
183
+ tffile = tempfile.NamedTemporaryFile(delete=False)
184
+ tffile.write(image_file_buffer.read())
185
+ tffile.close() # Ensure the file is closed before using it
186
+ img = cv2.imread(tffile.name)
187
+ st.text('Input Image')
188
+ st.image(img, use_column_width=True)
189
+
190
+ if st.button('Process Image'):
191
+ results = process_image(img)
192
+ license_plate_class_index = 1 # Update this if needed for your model
193
+
194
+ detected_classes = [] # To store detected classes from character segmentation
195
+
196
+ # Filter results for license plate class
197
+ for result in results:
198
+ filtered_boxes = [box for box in result.boxes if int(box.cls.item()) == license_plate_class_index]
199
+ for box in filtered_boxes:
200
+ try:
201
+ cls = int(box.cls.item())
202
+ conf = float(box.conf.item())
203
+ label = f"{license_plate_model.names[cls]} {conf:.2f}"
204
+ x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
205
+
206
+ cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)
207
+ cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
208
+
209
+ # Extract the license plate region, resize it, and pass it to the character model
210
+ license_plate_region = img[y1:y2, x1:x2]
211
+ zoomed_license_plate = cv2.resize(license_plate_region, (224, 224)) # Adjust size as needed
212
+ char_results = character_model.predict(zoomed_license_plate)
213
+ # Draw character boxes on the original image
214
+ char_boxes = []
215
+ for char_result in char_results:
216
+ for char_box in char_result.boxes:
217
+ try:
218
+ char_cls = int(char_box.cls.item())
219
+ char_conf = float(char_box.conf.item())
220
+ char_label = f"{character_model.names[char_cls]} {char_conf:.2f}"
221
+ char_x1, char_y1, char_x2, char_y2 = map(int, char_box.xyxy[0].tolist())
222
+
223
+ # Adjust coordinates relative to the original image
224
+ orig_char_x1 = x1 + char_x1 * ((x2 - x1) / 224)
225
+ orig_char_y1 = y1 + char_y1 * ((y2 - y1) / 224)
226
+ orig_char_x2 = x1 + char_x2 * ((x2 - x1) / 224)
227
+ orig_char_y2 = y1 + char_y2 * ((y2 - y1) / 224)
228
+
229
+ cv2.rectangle(img, (int(orig_char_x1), int(orig_char_y1)), (int(orig_char_x2), int(orig_char_y2)), (0, 255, 0), 2)
230
+ cv2.putText(img, char_label, (int(orig_char_x1), int(orig_char_y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
231
+ detected_classes.append((character_model.names[char_cls], orig_char_x1, orig_char_y1))
232
+ char_boxes.append(((character_model.names[char_cls], orig_char_x1, orig_char_y1), (int(orig_char_x1), int(orig_char_y1), int(orig_char_x2), int(orig_char_y2))))
233
+ except Exception as e:
234
+ st.write(f"Error processing character box: {e}")
235
+ st.write(f"Character box data: {char_box}")
236
+ except Exception as e:
237
+ st.write(f"Error processing license plate box: {e}")
238
+ st.write(f"License plate box data: {box}")
239
+
240
+ st.image(img, caption='Processed Image', use_column_width=True)
241
+
242
+ # Group detected classes by their y-coordinates
243
+ grouped_classes = defaultdict(list)
244
+ for cls, x, y in detected_classes:
245
+ grouped_classes[int(y // 20)].append((cls, x)) # Adjust the divisor (20) as needed based on character height
246
+
247
+ # Sort each group by x-coordinate
248
+ for key in grouped_classes:
249
+ grouped_classes[key].sort(key=lambda x: x[1])
250
+
251
+ # Print detected classes in order for each row
252
+ st.sidebar.markdown("### Detected Character Classes (Ordered by Rows)")
253
+ row_counter = 1
254
+ for key in sorted(grouped_classes.keys()):
255
+ st.sidebar.write(f"Row {row_counter}:")
256
+ c = ""
257
+ for cls, _ in grouped_classes[key]:
258
+ c += cls
259
+ st.sidebar.write(c)
260
+ row_counter += 1
261
+
262
+ # Check if any detected class belongs to Bagmati State
263
+ if any("BA" in cls or "Bagmati" in cls for cls, _, _ in detected_classes):
264
+ st.sidebar.write("It belongs to Bagmati State")
265
+
266
+ time.sleep(1) # Wait for a second before attempting to delete the file
267
+
268
+ def is_file_in_use(filepath):
269
+ try:
270
+ os.rename(filepath, filepath)
271
+ return False
272
+ except OSError:
273
+ return True
274
+
275
+ if not is_file_in_use(tffile.name):
276
+ try:
277
+ os.remove(tffile.name)
278
+ except Exception as e:
279
+ st.write(f"Error deleting temporary image file: {e}")
280
+
281
+ if __name__ == '__main__':
282
+ main()
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9aae5827464c7fcfaefd13e1c69ed8c82af1ae4cf89ec9f02e350ec1e1114897
3
+ size 6259811
best24.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3d5c707c1930c1d2a75a1eb80547d16dd676e94fc1f8333a2593d8358c3400e6
3
+ size 6252121
demo0.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aa6173fe1e8f6e353eb1f678ad4a64f27211b2c5272b77e5d34ae3dda1a6c86a
3
+ size 5230036
dockerfile ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY ./best24.pt /code/best24.pt
10
+ COPY ./best.pt /code/best.pt
11
+ COPY ./app.py /code/app.py
12
+ COPY ./demo0.mp4 /code/demo0.mp4
13
+
14
+ CMD ["streamlit", "run","-w","app.py", "--server.port=", "8080"]
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
requirements.txt ADDED
Binary file (2.8 kB). View file