Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.

Commit d5920ad

Browse files
authored
Merge pull request #141 from Azure-Samples/yadavm_factoryai
Yadavm factoryai
2 parents 1e04748 + 146f3de commit d5920ad

File tree

164 files changed

+3886
-2602
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+3886
-2602
lines changed

factory-ai-vision/EdgeSolution/modules/InferenceModule/main.py

Lines changed: 62 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ def is_inside_aoi(x1, y1, x2, y2, aoi_info):
4848
return True
4949
return False
5050

51+
def parse_bbox(prediction, width, height):
52+
x1 = int(prediction['boundingBox']['left'] * width)
53+
y1 = int(prediction['boundingBox']['top'] * height)
54+
x2 = x1 + int(prediction['boundingBox']['width'] * width)
55+
y2 = y1 + int(prediction['boundingBox']['height'] * height)
56+
return (x1, y1), (x2, y2)
57+
58+
59+
def draw_confidence_level(img, prediction):
60+
height, width = img.shape[0], img.shape[1]
61+
62+
font = cv2.FONT_HERSHEY_SIMPLEX
63+
font_scale = 1
64+
thickness = 3
65+
66+
prob_str = str(int(prediction['probability']*1000)/10)
67+
prob_str = ' (' + prob_str + '%)'
68+
69+
(x1, y1), (x2, y2) = parse_bbox(prediction, width, height)
70+
71+
img = cv2.putText(img, prediction['tagName']+prob_str, (x1+10, y1+30), font, font_scale, (0, 0, 255), thickness)
72+
73+
return img
74+
5175

5276
class ONNXRuntimeModelDeploy(ObjectDetection):
5377
"""Object Detection class for ONNX Runtime
@@ -225,20 +249,8 @@ def run(self):
225249
detection = DETECTION_TYPE_NOTHING
226250
if True:
227251
send_counter += 1
228-
# Modify here to change the threshold (deprecated)
229-
#if send_counter == 200:
230-
# if iot:
231-
# iot.send_message_to_output(json.dumps(self.last_prediction), 'metrics')
232-
# else:
233-
# print('[METRICS]', json.dumps(self.last_prediction))
234-
# send_counter = 0
235252
if self.iothub_is_send:
236253
if self.iothub_last_send_time + self.iothub_interval < time.time():
237-
#print('1', self.iothub_last_send_time)
238-
#print('2', self.iothub_interval)
239-
#print('3', self.iothub_last_send_time + self.iothub_interval)
240-
#print('4', time.time())
241-
#print('wew')
242254
predictions_to_send = []
243255
for prediction in self.last_prediction:
244256
_tag = prediction['tagName']
@@ -262,40 +274,38 @@ def run(self):
262274
pass
263275
self.iothub_last_send_time = time.time()
264276

265-
266-
267-
268277
for prediction in self.last_prediction:
269278

270279
tag = prediction['tagName']
271-
if tag not in self.parts: continue
272-
273-
if self.last_upload_time + UPLOAD_INTERVAL < time.time():
274-
x1 = int(prediction['boundingBox']['left'] * width)
275-
y1 = int(prediction['boundingBox']['top'] * height)
276-
x2 = x1 + int(prediction['boundingBox']['width'] * width)
277-
y2 = y1 + int(prediction['boundingBox']['height'] * height)
278-
labels = json.dumps([{'x1': x1, 'x2': x2, 'y1': y1, 'y2': y2}])
280+
if tag not in self.parts:
281+
continue
279282

280-
if self.has_aoi:
281-
if not is_inside_aoi(x1, y1, x2, y2, self.aoi_info): continue
283+
(x1, y1) , (x2, y2) = parse_bbox(prediction, width, height)
284+
if self.has_aoi:
285+
if not is_inside_aoi(x1, y1, x2, y2, self.aoi_info): continue
282286

283-
if prediction['probability'] > self.confidence_max:
287+
if detection != DETECTION_TYPE_SUCCESS:
288+
if prediction['probability'] >= self.threshold:
284289
detection = DETECTION_TYPE_SUCCESS
285-
286-
elif self.confidence_min <= prediction['probability'] <= self.confidence_max:
287-
288-
if detection != DETECTION_TYPE_SUCCESS: detection = DETECTION_TYPE_UNIDENTIFIED
290+
else:
291+
detection = DETECTION_TYPE_UNIDENTIFIED
289292

290293

294+
if self.last_upload_time + UPLOAD_INTERVAL < time.time():
295+
if self.confidence_min <= prediction['probability'] <= self.confidence_max:
291296
if self.is_upload_image:
292-
if tag in onnx.current_uploaded_images and self.current_uploaded_images[tag] >= onnx.max_images:
293-
pass
294-
else:
295-
self.current_uploaded_images[tag] = self.current_uploaded_images.get(tag, 0) + 1
296-
#print(tag, onnx.current_uploaded_images[tag], j)
297+
#if tag in onnx.current_uploaded_images and self.current_uploaded_images[tag] >= onnx.max_images:
298+
#if tag in onnx.current_uploaded_images:
299+
# No limit for the max_images in inference module now, the logic is moved to webmodule
300+
# pass
301+
#else:
302+
if True:
303+
304+
labels = json.dumps([{'x1': x1, 'x2': x2, 'y1': y1, 'y2': y2}])
305+
print('[INFO] Sending Image to relabeling', tag, onnx.current_uploaded_images.get(tag, 0), labels)
306+
#self.current_uploaded_images[tag] = self.current_uploaded_images.get(tag, 0) + 1
297307
self.last_upload_time = time.time()
298-
print('[INFO] Sending Image to relabeling', tag, onnx.current_uploaded_images[tag], labels)
308+
299309
jpg = cv2.imencode('.jpg', img)[1].tobytes()
300310
try:
301311
requests.post('http://'+web_module_url()+'/api/relabel', data={
@@ -324,15 +334,14 @@ def run(self):
324334
self.detection_unidentified_num += 1
325335
elif detection == DETECTION_TYPE_SUCCESS:
326336
self.detection_success_num += 1
327-
328337
else:
329338
self.detections.append(detection)
330339
if detection == DETECTION_TYPE_UNIDENTIFIED:
331340
self.detection_unidentified_num += 1
332341
elif detection == DETECTION_TYPE_SUCCESS:
333342
self.detection_success_num += 1
334343
self.detection_total += 1
335-
344+
336345
self.lock.release()
337346
#print(detection)
338347
else:
@@ -389,7 +398,7 @@ def metrics():
389398

390399
@app.route('/update_retrain_parameters')
391400
def update_retrain_parameters():
392-
401+
393402
confidence_min = request.args.get('confidence_min')
394403
if not confidence_min: return 'missing confidence_min'
395404

@@ -485,15 +494,10 @@ def update_parts():
485494

486495
return 'ok'
487496

488-
@app.route('/update_threshold')
489-
def update_threshold():
490-
#threshold = float(request.args.get('threshold'))
491-
492-
#print('[INFO] update theshold to', threshold)
493-
494-
#onnx.threshold = threshold
495-
print('[WARNING] is depreciated')
496-
return 'ok'
497+
#@app.route('/update_threshold')
498+
#def update_threshold():
499+
# print('[WARNING] is depreciated')
500+
# return 'ok'
497501

498502
@app.route('/update_iothub_parameters')
499503
def update_iothub_parameters():
@@ -527,6 +531,13 @@ def update_prob_threshold():
527531
print('[INFO] updaing prob_threshold to')
528532
print(' prob_threshold:', prob_threshold)
529533

534+
onnx.lock.acquire()
535+
onnx.detection_success_num = 0
536+
onnx.detection_unidentified_num = 0
537+
onnx.detection_total = 0
538+
onnx.detections = []
539+
onnx.lock.release()
540+
530541
return 'ok'
531542

532543
@app.route('/video_feed')
@@ -539,9 +550,6 @@ def _gen():
539550
if inference:
540551
height, width = img.shape[0], img.shape[1]
541552
predictions = onnx.last_prediction
542-
font = cv2.FONT_HERSHEY_SIMPLEX
543-
font_scale = 1
544-
thickness = 3
545553
for prediction in predictions:
546554
tag = prediction['tagName']
547555
if tag not in onnx.parts: continue
@@ -550,33 +558,22 @@ def _gen():
550558
for aoi_area in onnx.aoi_info:
551559
img = cv2.rectangle(img, (int(aoi_area['x1']), int(aoi_area['y1'])), (int(aoi_area['x2']), int(aoi_area['y2'])), (0, 255, 255), 2)
552560

553-
#if prediction['probability'] > onnx.confidence_max:
554-
#print(prediction)
555561
if prediction['probability'] > onnx.threshold:
556-
x1 = int(prediction['boundingBox']['left'] * width)
557-
y1 = int(prediction['boundingBox']['top'] * height)
558-
x2 = x1 + int(prediction['boundingBox']['width'] * width)
559-
y2 = y1 + int(prediction['boundingBox']['height'] * height)
562+
(x1, y1), (x2, y2) = parse_bbox(prediction, width, height)
560563
if onnx.has_aoi:
561564
if not is_inside_aoi(x1, y1, x2, y2, onnx.aoi_info): continue
562565

563566
img = cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
564-
prob_str = str(int(prediction['probability']*1000)/10)
565-
prob_str = ' (' + prob_str + '%)'
566-
img = cv2.putText(img, prediction['tagName']+prob_str, (x1+10, y1+30), font, font_scale, (0, 0, 255), thickness)
567+
img = draw_confidence_level(img, prediction)
567568

568569

569-
time.sleep(0.03)
570+
time.sleep(0.02)
570571
yield (b'--frame\r\n'
571572
b'Content-Type: image/jpeg\r\n\r\n' + cv2.imencode('.jpg', img)[1].tobytes() + b'\r\n')
572573

573574
return Response(_gen(),
574575
mimetype='multipart/x-mixed-replace; boundary=frame')
575576

576-
# for debugging
577-
#onnx.update_cam(cam_type='rtsp', cam_source='sample_video/video.mp4', has_aoi=True, aoi_info={'x1': 100, 'x2': 1000, 'y1': 100, 'y2': 500})
578-
#requests.get('http://localhost:5000/update_cam', params={'cam_type':'rtsp', 'cam_source':'0', 'aoi':'{\"useAOI\":true,\"AOIs\":[{\"x1\":100,\"y1\":216.36363636363637,\"x2\":3314.909090909091,\"y2\":1762.181818181818}]}'})
579-
580577

581578
def main():
582579

factory-ai-vision/EdgeSolution/modules/InferenceModule/module.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"image": {
55
"repository": "${CONTAINER_REGISTRY_NAME}/intelligentedge/inferencemodule",
66
"tag": {
7-
"version": "0.1.70",
7+
"version": "0.1.74",
88
"platforms": {
99
"cpuamd64": "./Dockerfile.cpuamd64",
1010
"gpuamd64": "./Dockerfile.gpuamd64",

factory-ai-vision/EdgeSolution/modules/WebModule/backend/README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Camera App
1+
# Vision On Edge Web Module
22

33
## How to run
44

@@ -35,12 +35,11 @@ pylint
3535
Go to project directory (same level with manage.py)
3636

3737
```bash
38-
python manage.py test cameras.tests
38+
python manage.py test
3939
```
4040

4141
## Test coverage
4242

4343
```bash
44-
coverage run --source='cameras' manage.py test cameras.tests
44+
coverage run --source='vision_on_edge' manage.py test vision_on_edge.tests
4545
```
46-

factory-ai-vision/EdgeSolution/modules/WebModule/backend/configs/api.py

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Websocket router
3+
"""
4+
from channels.routing import ProtocolTypeRouter, URLRouter
5+
from channels.security.websocket import AllowedHostsOriginValidator
6+
from django.conf.urls import url
7+
8+
from vision_on_edge.notifications.consumers import NotificationConsumer
9+
10+
application = ProtocolTypeRouter({
11+
# (http->django views is added by default)
12+
'websocket':
13+
AllowedHostsOriginValidator(
14+
URLRouter([
15+
url(r"api/notifications", NotificationConsumer),
16+
]))
17+
})

factory-ai-vision/EdgeSolution/modules/WebModule/backend/configs/settings.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,16 @@
4444
'django.contrib.messages',
4545
'django.contrib.staticfiles',
4646
'corsheaders',
47+
'channels',
48+
'vision_on_edge.azure_parts',
49+
'vision_on_edge.images',
50+
'vision_on_edge.streams',
4751
'vision_on_edge.azure_settings',
4852
'vision_on_edge.locations',
4953
'vision_on_edge.cameras',
5054
'vision_on_edge.image_predictions',
5155
'vision_on_edge.azure_training',
56+
'vision_on_edge.notifications',
5257
'rest_framework',
5358
'drf_yasg',
5459
]
@@ -99,8 +104,7 @@
99104

100105
CORS_ORIGIN_ALLOW_ALL = True
101106

102-
# WSGI_APPLICATION = 'vision_on_edge.wsgi.application'
103-
ASGI_APPLICATION = 'vision_on_edge.asgi.application'
107+
ASGI_APPLICATION = 'configs.routing.application'
104108

105109
# Database
106110
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
@@ -163,6 +167,12 @@
163167
ICON_URL = '/icons/'
164168
ICON_ROOT = os.path.join(UI_DIR, 'icons')
165169

170+
CHANNEL_LAYERS = {
171+
"default": {
172+
"BACKEND": "channels.layers.InMemoryChannelLayer"
173+
}
174+
}
175+
166176
IOT_HUB_CONNECTION_STRING = config.IOT_HUB_CONNECTION_STRING
167177
DEVICE_ID = config.DEVICE_ID
168178
MODULE_ID = config.MODULE_ID

factory-ai-vision/EdgeSolution/modules/WebModule/backend/configs/urls.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@
2020
from django.urls import path
2121
from rest_framework import routers
2222

23-
from vision_on_edge.azure_settings.api import views as setting_views
23+
from vision_on_edge.azure_parts.api import views as azure_part_views
24+
from vision_on_edge.azure_settings.api import views as azure_setting_views
2425
from vision_on_edge.azure_training.api import views as azure_training_views
2526
from vision_on_edge.cameras.api import util_views as camera_util_views
2627
from vision_on_edge.cameras.api import views
2728
from vision_on_edge.image_predictions.api import \
2829
views as image_prediction_views
30+
from vision_on_edge.images.api import views as image_views
2931
from vision_on_edge.locations.api import views as location_views
30-
32+
from vision_on_edge.relabeling.api import views as relabel_views
33+
from vision_on_edge.streams.api import views as stream_views
34+
from vision_on_edge.notifications.api import views as notifications_views
3135
from . import views as site_views
3236

3337

@@ -41,34 +45,36 @@ def __init__(self):
4145

4246
#router = ters.DefaultRouter(trailing_slash=False)
4347
router = OptionalSlashRouter()
44-
router.register('settings', setting_views.SettingViewSet)
48+
router.register('settings', azure_setting_views.SettingViewSet)
4549
router.register('cameras', views.CameraViewSet)
46-
router.register('parts', views.PartViewSet)
47-
router.register('images', views.ImageViewSet)
50+
router.register('parts', azure_part_views.PartViewSet)
4851
router.register('locations', location_views.LocationViewSet)
49-
router.register('annotations', views.AnnotationViewSet)
5052
router.register('image_predictions',
5153
image_prediction_views.ImagePredictionViewSet)
5254
router.register('projects', azure_training_views.ProjectViewSet)
5355
router.register('train', azure_training_views.TrainViewSet)
5456
router.register('tasks', azure_training_views.TaskViewSet)
57+
router.register('images', image_views.ImageViewSet)
58+
router.register('notifications', notifications_views.NotificationViewSet)
59+
router.register('images', image_views.ImageViewSet)
5560

5661
urlpatterns = \
5762
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + \
5863
static(settings.ICON_URL, document_root=settings.ICON_ROOT) + \
5964
[
6065
url('^api/', include(router.urls)),
61-
url('api/streams/connect', views.connect_stream),
62-
path('api/streams/<int:stream_id>/disconnect', views.disconnect_stream),
63-
path('api/streams/<int:stream_id>/video_feed', views.video_feed),
64-
path('api/streams/<int:stream_id>/capture', views.capture),
66+
url('api/streams/connect', stream_views.connect_stream),
67+
path('api/streams/<int:stream_id>/disconnect',
68+
stream_views.disconnect_stream),
69+
path('api/streams/<int:stream_id>/video_feed', stream_views.video_feed),
70+
path('api/streams/<int:stream_id>/capture', stream_views.capture),
6571
path('api/projects/<int:project_id>/train', azure_training_views.train),
6672
path('api/projects/<int:project_id>/export',
6773
azure_training_views.export),
6874
path('api/projects/<int:project_id>/train_performance',
6975
azure_training_views.train_performance),
7076
path('api/projects/<int:project_id>/inference_video_feed',
71-
views.inference_video_feed),
77+
stream_views.inference_video_feed),
7278
path('api/projects/<int:project_id>/pull_cv_project',
7379
azure_training_views.pull_cv_project),
7480
path('api/projects/<int:project_id>/update_prob_threshold',
@@ -78,8 +84,8 @@ def __init__(self):
7884
path('api/projects/<int:project_id>/reset_camera',
7985
azure_training_views.project_reset_camera),
8086
path('api/projects/null/export', azure_training_views.export_null),
81-
path('api/relabel', views.upload_relabel_image),
82-
path('api/relabel/update', views.relabel_update),
87+
path('api/relabel', relabel_views.upload_relabel_image),
88+
path('api/relabel/update', relabel_views.relabel_update),
8389
path('api/appinsight/key', views.instrumentation_key),
8490
path('api/camera_utils/verify_rtsp',
8591
camera_util_views.verify_rtsp),

0 commit comments

Comments
 (0)