pyesonekyaw commited on
Commit
2d4f58a
1 Parent(s): 7800abd

initial commit

Browse files
.gitattributes CHANGED
@@ -32,3 +32,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ *.jpg filter=lfs diff=lfs merge=lfs -text
Examples/1.jpg ADDED

Git LFS Details

  • SHA256: 6f2a63ce3113a407abf6b522f637c3f2332962e380190b579c81f74deb4a1853
  • Pointer size: 131 Bytes
  • Size of remote file: 909 kB
Examples/10.jpg ADDED

Git LFS Details

  • SHA256: 913f1ff34a6f7170a99e79565e11e452bb31938c214d182cd98f16771c6bcd5c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.07 MB
Examples/11.jpg ADDED

Git LFS Details

  • SHA256: dffe64b021a31d0c6cc7caa494c5d2a0474b76701bd9acd52303afe3b735cdcb
  • Pointer size: 131 Bytes
  • Size of remote file: 599 kB
Examples/12.jpg ADDED

Git LFS Details

  • SHA256: 0bdafc6b4cd54497039a5c39318573310c68626755416bf04e4cfff2e9973fcc
  • Pointer size: 131 Bytes
  • Size of remote file: 759 kB
Examples/2.jpg ADDED

Git LFS Details

  • SHA256: 98b4bb6bc7815d57122a63f0db6a2a28bfa086c59f0329410c2b7db7fbb7dc0e
  • Pointer size: 132 Bytes
  • Size of remote file: 1.25 MB
Examples/3.jpg ADDED

Git LFS Details

  • SHA256: 2808ba03287664a1e4ec31cf0a3e9ec4278a4786c5963aa71fb2a74b9693e0fd
  • Pointer size: 132 Bytes
  • Size of remote file: 1.11 MB
Examples/4.jpg ADDED

Git LFS Details

  • SHA256: 7c4168084bd47a9b12fbaecd08cb98338b9844771281e5cd42b217e799164aef
  • Pointer size: 131 Bytes
  • Size of remote file: 611 kB
Examples/5.jpg ADDED

Git LFS Details

  • SHA256: 20140da8d81fe6d790b9b2ffa57dca7fc3f3bc43d93236c2106d038408d373e8
  • Pointer size: 131 Bytes
  • Size of remote file: 465 kB
Examples/6.jpg ADDED

Git LFS Details

  • SHA256: 160e1b9cea1c6f7a0e463416b49863f0a9f01a52b1d2f46c594df95bdab0c435
  • Pointer size: 130 Bytes
  • Size of remote file: 37.5 kB
Examples/7.jpg ADDED

Git LFS Details

  • SHA256: 4548935fdec1b6d3a78b3276294f0e344cc2c7fbfe64482c1891944fe45f89df
  • Pointer size: 130 Bytes
  • Size of remote file: 31.7 kB
Examples/8.jpg ADDED

Git LFS Details

  • SHA256: 9e8e90dbe787dac6e3457758287a4dda7ef2fbe71ff050724422c049146d2f93
  • Pointer size: 130 Bytes
  • Size of remote file: 34.3 kB
Examples/9.jpg ADDED

Git LFS Details

  • SHA256: 4a70d70fea521ff6782c19562e9ba919220e5904da8cabaafbde80c4e290fa76
  • Pointer size: 130 Bytes
  • Size of remote file: 31.7 kB
Examples/One.jpg ADDED

Git LFS Details

  • SHA256: 2fb210c9c6029f007502c0a83796cb8d3ea26e0f942b143114bc1d12df92924e
  • Pointer size: 131 Bytes
  • Size of remote file: 101 kB
Examples/Three.jpg ADDED

Git LFS Details

  • SHA256: 4347c491a181f05397b730d88653b120f2852e420668f35c23acc708eaa0a698
  • Pointer size: 131 Bytes
  • Size of remote file: 116 kB
Examples/Two.jpg ADDED

Git LFS Details

  • SHA256: 3d3e90a880ebe3ad35daee9e69a83c33926d5d464003af4c4f0ce98f73bbc236
  • Pointer size: 131 Bytes
  • Size of remote file: 110 kB
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: Image Recognition-CZ3004 SC2079 Multidisciplinary Project-NTU SG
3
- emoji: 🐢
4
  colorFrom: indigo
5
  colorTo: green
6
  sdk: gradio
 
1
  ---
2
  title: Image Recognition-CZ3004 SC2079 Multidisciplinary Project-NTU SG
3
+ emoji: 🔣
4
  colorFrom: indigo
5
  colorTo: green
6
  sdk: gradio
Weights/Week_8.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1cdc1c277dbbc29901e2463616e19fd74592eefca3224be23d4f54ffac2c69e9
3
+ size 57300618
Weights/Week_9.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e6a050ce6e9fe9711d1a41aed0934ece185611d7081b12eb8eab0332c7a71307
3
+ size 14318653
app.py ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from PIL import Image
4
+ import json
5
+ import numpy as np
6
+ import cv2
7
+ week8_model = torch.hub.load(
8
+ './', 'custom', path='Weights/Week_8.pt', source='local')
9
+ week9_model = torch.hub.load(
10
+ './', 'custom', path='Weights/Week_9.pt', source='local')
11
+
12
+ def draw_own_bbox(img,x1,y1,x2,y2,label,color=(36,255,12),text_color=(0,0,0)):
13
+ """
14
+ Draw bounding box on the image with text label and save both the raw and annotated image in the 'own_results' folder
15
+
16
+ Inputs
17
+ ------
18
+ img: numpy.ndarray - image on which the bounding box is to be drawn
19
+
20
+ x1: int - x coordinate of the top left corner of the bounding box
21
+
22
+ y1: int - y coordinate of the top left corner of the bounding box
23
+
24
+ x2: int - x coordinate of the bottom right corner of the bounding box
25
+
26
+ y2: int - y coordinate of the bottom right corner of the bounding box
27
+
28
+ label: str - label to be written on the bounding box
29
+
30
+ color: tuple - color of the bounding box
31
+
32
+ text_color: tuple - color of the text label
33
+
34
+ Returns
35
+ -------
36
+ None
37
+
38
+ """
39
+ name_to_id = {
40
+ "NA": 'NA',
41
+ "Bullseye": 10,
42
+ "One": 11,
43
+ "Two": 12,
44
+ "Three": 13,
45
+ "Four": 14,
46
+ "Five": 15,
47
+ "Six": 16,
48
+ "Seven": 17,
49
+ "Eight": 18,
50
+ "Nine": 19,
51
+ "A": 20,
52
+ "B": 21,
53
+ "C": 22,
54
+ "D": 23,
55
+ "E": 24,
56
+ "F": 25,
57
+ "G": 26,
58
+ "H": 27,
59
+ "S": 28,
60
+ "T": 29,
61
+ "U": 30,
62
+ "V": 31,
63
+ "W": 32,
64
+ "X": 33,
65
+ "Y": 34,
66
+ "Z": 35,
67
+ "Up": 36,
68
+ "Down": 37,
69
+ "Right": 38,
70
+ "Left": 39,
71
+ "Up Arrow": 36,
72
+ "Down Arrow": 37,
73
+ "Right Arrow": 38,
74
+ "Left Arrow": 39,
75
+ "Stop": 40
76
+ }
77
+ # Reformat the label to {label name}-{label id}
78
+ label = label + "-" + str(name_to_id[label])
79
+ # Convert the coordinates to int
80
+ x1 = int(x1)
81
+ x2 = int(x2)
82
+ y1 = int(y1)
83
+ y2 = int(y2)
84
+
85
+ # Save the raw image
86
+ # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
87
+
88
+ # Draw the bounding box
89
+ img = cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)
90
+ # For the text background, find space required by the text so that we can put a background with that amount of width.
91
+ (w, h), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 1)
92
+ # Print the text
93
+ img = cv2.rectangle(img, (x1, y1 - 20), (x1 + w, y1), color, -1)
94
+ img = cv2.putText(img, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, text_color, 1)
95
+ return img
96
+
97
+ def yolo(img, model, toggles, signal, size=1024):
98
+ if model == "Week 8":
99
+ model = week8_model
100
+ else:
101
+ model = week9_model
102
+
103
+ results = model(img)
104
+
105
+ # Original output image and results
106
+ original_results = json.loads(results.pandas().xyxy[0].to_json(orient="records"))
107
+ output_image = Image.fromarray(results.render()[0])
108
+
109
+ # Convert the results to a pandas dataframe and calculate the height and width of the bounding box and the area of the bounding box
110
+ df_results = results.pandas().xyxy[0]
111
+ df_results['bboxHt'] = df_results['ymax'] - df_results['ymin']
112
+ df_results['bboxWt'] = df_results['xmax'] - df_results['xmin']
113
+ df_results['bboxArea'] = df_results['bboxHt'] * df_results['bboxWt']
114
+
115
+ # Label with largest bbox height will be last
116
+ df_results = df_results.sort_values('bboxArea', ascending=False)
117
+
118
+ # Filter out Bullseye
119
+ pred_list = df_results
120
+ if 'Ignore Bullseye' in toggles:
121
+ pred_list = pred_list[pred_list['name'] != 'Bullseye']
122
+
123
+ if len(pred_list) == 0:
124
+ return [output_image, original_results, output_image, original_results]
125
+
126
+ elif len(pred_list) == 1:
127
+ pred = pred_list.iloc[0]
128
+
129
+ else:
130
+ pred_shortlist = []
131
+ current_area = pred_list.iloc[0]['bboxArea']
132
+
133
+ # For each prediction, check if the confidence is greater than 0.5 and if the area is greater than 80% of the current area or 60% if the prediction is 'One'
134
+ for _, row in pred_list.iterrows():
135
+ if row['confidence'] > 0.5 and ((current_area * 0.8 <= row['bboxArea']) or (row['name'] == 'One' and current_area * 0.6 <= row['bboxArea'])):
136
+ # Add the prediction to the shortlist
137
+ pred_shortlist.append(row)
138
+ # Update the current area to the area of the prediction
139
+ current_area = row['bboxArea']
140
+
141
+ # If only 1 prediction remains after filtering by confidence and area
142
+ if len(pred_shortlist) == 1:
143
+ # Choose that prediction
144
+ pred = pred_shortlist[0]
145
+
146
+ # If multiple predictions remain after filtering by confidence and area
147
+ else:
148
+ # Use signal of {signal} to filter further
149
+
150
+ # Sort the predictions by xmin
151
+ pred_shortlist.sort(key=lambda x: x['xmin'])
152
+
153
+ # If signal is 'L', choose the first prediction in the list, i.e. leftmost in the image
154
+ if signal == 'L':
155
+ pred = pred_shortlist[0]
156
+
157
+ # If signal is 'R', choose the last prediction in the list, i.e. rightmost in the image
158
+ elif signal == 'R':
159
+ pred = pred_shortlist[-1]
160
+
161
+ # If signal is 'C', choose the prediction that is central in the image
162
+ else:
163
+ # Loop through the predictions shortlist
164
+ for i in range(len(pred_shortlist)):
165
+ # If the xmin of the prediction is between 250 and 774, i.e. the center of the image, choose that prediction
166
+ if pred_shortlist[i]['xmin'] > 250 and pred_shortlist[i]['xmin'] < 774:
167
+ pred = pred_shortlist[i]
168
+ break
169
+
170
+ # If no prediction is central, choose the one with the largest area
171
+ if isinstance(pred,str):
172
+ # Choosing one with largest area if none are central
173
+ pred_shortlist.sort(key=lambda x: x['bboxArea'])
174
+ pred = pred_shortlist[-1]
175
+
176
+
177
+ filtered_img = draw_own_bbox(np.array(img), pred['xmin'], pred['ymin'], pred['xmax'], pred['ymax'], pred['name'])
178
+ return [output_image, original_results, filtered_img, json.loads(pred.to_json(orient="records"))]
179
+
180
+
181
+ inputs = [gr.inputs.Image(type='pil', label="Original Image"),
182
+ gr.inputs.Radio(['Week 8', 'Week 9'], type="value", default='Week 8', label='Model Selection'),
183
+ gr.CheckboxGroup(["Ignore Bullseye", "Biggest BBox Only and Position-Based Heuristics",], value=["Ignore Bullseye", "Biggest BBox Only and Position-Based Heuristics"], label="Heuristic Toggles"),
184
+ gr.inputs.Radio(['Left', 'Center', 'Right', 'Disabled'], type="value", default='Center', label='Position Heuristic'),
185
+ ]
186
+ outputs = [gr.outputs.Image(type="pil", label="Output Image"),
187
+ gr.outputs.JSON(label="Output JSON"),
188
+ gr.outputs.Image(type="pil", label="Filtered Output Image"),
189
+ gr.outputs.JSON(label="Filtered Output JSON")
190
+ ]
191
+
192
+ examples = [['Examples/One.jpg'], ['Examples/Two.jpg'], ['Examples/Three.jpg'], ['Examples/1.jpg'], ['Examples/2.jpg'], ['Examples/3.jpg'], ['Examples/4.jpg'], ['Examples/5.jpg'], ['Examples/6.jpg'],
193
+ ['Examples/7.jpg'], ['Examples/8.jpg'], ['Examples/9.jpg'], ['Examples/10.jpg'], ['Examples/11.jpg'], ['Examples/12.jpg']]
194
+
195
+
196
+ with gr.Blocks(css="#custom_header {min-height: 2rem; text-align: center} #custom_title {min-height: 2rem}") as demo:
197
+ gr.Markdown("# YOLOv5 Symbol Recognition for CZ3004/SC2079 Multi-Disciplinary Project", elem_id="custom_header")
198
+ gr.Markdown("Gradio Demo for YOLOv5 Symbol Recognition for CZ3004 Multi-Disciplinary Project. To use it, simply upload your image, or click one of the examples to load them.", elem_id="custom_header")
199
+ gr.Markdown("CZ3004 is a module in Nanyang Technological University's Computer Science curriculum that involves creating a robot car that can navigate within an arena and around obstacles. Part of the assessment is to go to obstacles and detect alphanumeric symbols pasted on them.", elem_id="custom_title")
200
+ gr.Markdown("The two models available, Week 8 and Week 9, are for different subtasks. Week 8 model (as assessment was done in Week 8 of the school semester), \
201
+ is able to detect all symbols seen in the first three example images below. Week 9 model is limited to just the bullseye, left and right arrow symbols. \
202
+ Additionally, Week 9 model has been further trained on extreme edge cases where there is harsh sunlight behind the symbol/obstacle (seen in some of the examples).", elem_id="custom_title")
203
+ gr.Markdown("Heuristics used are based on the task as of AY22-23 Semester 2's edition of MDP. These include ignoring the bullseye symbol, taking only the biggest bounding box, and filtering similar sized detections by the expected position of the symbol based on where the robot is supposed to be relative to the symbol.", elem_id="custom_title")
204
+ gr.Markdown("This demo is part of a guide that is currently work-in-progress, for future CZ3004/SC2079 students to refer to.", elem_id="custom_title")
205
+
206
+
207
+ with gr.Row():
208
+ with gr.Column():
209
+ with gr.Box():
210
+ gr.Markdown("## Inputs", elem_id="custom_header")
211
+ input_image = gr.inputs.Image(type='pil', label="Original Image")
212
+ btn = gr.Button(value="Submit")
213
+ btn.style(full_width=True)
214
+ with gr.Column():
215
+ with gr.Box():
216
+ gr.Markdown("## Parameters", elem_id="custom_header")
217
+ model_selection = gr.inputs.Radio(['Week 8', 'Week 9'], type="value", default='Week 8', label='Model Selection')
218
+ toggles = gr.CheckboxGroup(["Ignore Bullseye", "Biggest BBox Only and Position-Based Heuristics",], value=["Ignore Bullseye", "Biggest BBox Only and Position-Based Heuristics"], label="Heuristic Toggles")
219
+ radios = gr.inputs.Radio(['Left', 'Center', 'Right', 'Disabled'], type="value", default='Center', label='Position Heuristic')
220
+ with gr.Row():
221
+ with gr.Box():
222
+ with gr.Column():
223
+ gr.Markdown("## Raw Outputs", elem_id="custom_header")
224
+ output_image = gr.outputs.Image(type="pil", label="Output Image")
225
+ output_json = gr.outputs.JSON(label="Output JSON")
226
+ with gr.Box():
227
+ with gr.Column():
228
+ gr.Markdown("## Filtered Outputs", elem_id="custom_header")
229
+ filtered_image = gr.outputs.Image(type="pil", label="Filtered Output Image")
230
+ filtered_json = gr.outputs.JSON(label="Filtered Output JSON")
231
+ with gr.Row():
232
+ gr.Examples(examples=examples,
233
+ inputs=input_image,
234
+ outputs=output_image,
235
+ fn=yolo,
236
+ cache_examples=False)
237
+ btn.click(yolo, inputs=[input_image, model_selection,toggles, radios], outputs=[output_image, output_json, filtered_image, filtered_json])
238
+
239
+ demo.launch(debug=True)