vagheshpatel commited on
Commit
0577537
·
verified ·
1 Parent(s): 8702645

Update native RC1 samples and supported device documentation

Browse files
Files changed (5) hide show
  1. README.md +67 -17
  2. config.json +11 -3
  3. dlstreamer_sample.py +88 -0
  4. export_and_quantize.sh +119 -11
  5. openvino_sample.py +103 -0
README.md CHANGED
@@ -8,6 +8,7 @@ tags:
8
  - intel
9
  - yolo
10
  - yolo26
 
11
  - object-classification
12
  - classification
13
  - smart-city
@@ -25,8 +26,8 @@ language:
25
  | Property | Value |
26
  |---|---|
27
  | **Category** | Object Classification (Traffic Categorization: People / Vehicles) |
28
- | **Base Model** | [YOLO26](https://docs.ultralytics.com/models/yolo26/) (Ultralytics) |
29
- | **Source Framework** | PyTorch (Ultralytics) |
30
  | **Supported Precisions** | FP32, FP16, INT8 (mixed-precision) |
31
  | **Inference Engine** | OpenVINO |
32
  | **Hardware** | CPU, GPU, NPU |
@@ -54,16 +55,35 @@ Typical Metro deployments include:
54
  - **Intersection and Roundabout Monitoring** -- track the mix of pedestrians and vehicles at busy junctions.
55
  - **Trend Analytics** -- aggregate category counts over time to understand traffic patterns.
56
 
57
- Available variants: `yolo26n`, `yolo26s`, `yolo26m`, `yolo26l`, `yolo26x`.
58
  Smaller variants (`yolo26n`, `yolo26s`) are recommended for high-FPS edge deployment; larger variants improve recall for small objects.
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  ---
61
 
62
  ## Prerequisites
63
 
 
 
 
 
64
  - Python 3.11+
65
  - [Install OpenVINO](https://docs.openvino.ai/2026/get-started/install-openvino.html) (latest version)
66
- - [Install Intel DLStreamer](https://docs.openedgeplatform.intel.com/2026.0/edge-ai-libraries/dlstreamer/get_started/install/install_guide_ubuntu.html) (latest version)
67
 
68
  Create and activate a Python virtual environment before running the scripts:
69
 
@@ -91,25 +111,27 @@ chmod +x export_and_quantize.sh
91
 
92
  This exports the default **yolo26n** model in **FP16** precision.
93
 
94
- #### Optional: Select a Different Variant or Precision
95
 
96
  ```bash
97
- ./export_and_quantize.sh yolo26n FP32 # full-precision
98
- ./export_and_quantize.sh yolo26n INT8 # quantized
99
- ./export_and_quantize.sh yolo26s # larger variant, default FP16
 
 
100
  ```
101
 
102
- Replace `yolo26n` with any variant (`yolo26s`, `yolo26m`, `yolo26l`, `yolo26x`).
103
  The second argument selects the precision (`FP32`, `FP16`, `INT8`); the default is **FP16**.
104
 
105
  The script performs the following steps:
106
 
107
- 1. Installs dependencies (`openvino`, `ultralytics`; adds `nncf` for INT8).
108
  2. Downloads a sample traffic video (`test_video.mp4`) of an urban roundabout at low resolution (640x360).
109
  3. Downloads the PyTorch weights and exports to OpenVINO IR.
110
  4. *(INT8 only)* Quantizes the model using NNCF post-training quantization.
111
 
112
- Output files:
113
 
114
  - `yolo26n_openvino_model/` -- FP32 or FP16 OpenVINO IR model directory.
115
  - `yolo26n_objcls_int8.xml` / `yolo26n_objcls_int8.bin` -- INT8 quantized model *(only when `INT8` is selected)*.
@@ -135,13 +157,24 @@ category, overlays live category counts, and writes the annotated result to
135
  YOLO26 is end-to-end (NMS-free), so no manual non-maximum suppression is needed.
136
  Change the `device` string to run on CPU, GPU, or NPU.
137
 
 
 
 
138
  ```python
 
 
 
 
 
 
139
  import cv2
140
  import numpy as np
141
  import openvino as ov
142
 
143
  CONF_THRESHOLD = 0.4
144
- INPUT_SIZE = 640
 
 
145
 
146
  # Map the traffic-relevant COCO class ids into higher-level city categories.
147
  # People and Vehicles are the two categories tracked for situational awareness.
@@ -161,7 +194,7 @@ CATEGORY_COLORS = {
161
  }
162
 
163
  core = ov.Core()
164
- model = core.read_model("yolo26n_openvino_model/yolo26n.xml")
165
 
166
  # YOLO26 embeds the 80 COCO class names in rt_info. Ultralytics separates
167
  # multi-word names with underscores (e.g. "traffic_light"), so restore spaces.
@@ -194,7 +227,8 @@ while True:
194
  blob = cv2.cvtColor(blob, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
195
  blob = blob.transpose(2, 0, 1)[np.newaxis, ...] # NCHW
196
 
197
- # YOLO26 end-to-end output: [1, 300, 6] = [x1, y1, x2, y2, confidence, class_id].
 
198
  output = compiled([blob])[output_port][0]
199
 
200
  sx, sy = width / INPUT_SIZE, height / INPUT_SIZE
@@ -231,6 +265,7 @@ writer.release()
231
  print(f"Summary: People={totals['People']} Vehicles={totals['Vehicles']}")
232
  print("Saved: output_openvino.mp4")
233
  ```
 
234
 
235
  **Device targets:**
236
 
@@ -268,7 +303,7 @@ classes only (non-traffic detections such as `handbag` are filtered out via
268
 
269
  > **Notes on running this sample:**
270
  >
271
- > - Use the FP16 IR (`yolo26n_openvino_model/yolo26n.xml`). Class names are
272
  > read automatically from the model's embedded `metadata.yaml` by
273
  > DLStreamer 2026.0+ -- no external `labels-file` is required.
274
  > - Export `PYTHONPATH` so the DLStreamer Python module is importable:
@@ -280,7 +315,16 @@ classes only (non-traffic detections such as `handbag` are filtered out via
280
  > /opt/intel/dlstreamer/gstreamer/lib/python3/dist-packages:${PYTHONPATH:-}
281
  > ```
282
 
 
 
 
283
  ```python
 
 
 
 
 
 
284
  import gi
285
 
286
  gi.require_version("Gst", "1.0")
@@ -302,6 +346,9 @@ CATEGORY_BY_LABEL = {
302
  "truck": "Vehicles",
303
  }
304
 
 
 
 
305
  # For CPU: change device=GPU to device=CPU.
306
  # For NPU: change device=GPU to device=NPU (batch-size=1, nireq=4 recommended).
307
  # gvawatermark displ-cfg:
@@ -311,7 +358,7 @@ CATEGORY_BY_LABEL = {
311
  pipeline_str = (
312
  f"filesrc location={INPUT_VIDEO} ! decodebin3 ! "
313
  "videoconvert ! "
314
- "gvadetect model=yolo26n_openvino_model/yolo26n.xml "
315
  "device=GPU "
316
  "threshold=0.4 ! queue ! "
317
  "gvawatermark "
@@ -361,6 +408,7 @@ bus.timed_pop_filtered(
361
  pipeline.set_state(Gst.State.NULL)
362
  print(f"Summary: People={totals['People']} Vehicles={totals['Vehicles']}")
363
  ```
 
364
 
365
  #### Expected Output
366
 
@@ -381,8 +429,10 @@ Licensed under the MIT License. See [LICENSE](LICENSE) for details.
381
  ## References
382
 
383
  - [YOLO26 Documentation](https://docs.ultralytics.com/models/yolo26/)
 
 
384
  - [OpenVINO YOLO26 Notebook](https://github.com/openvinotoolkit/openvino_notebooks/blob/latest/notebooks/yolov26-optimization/yolov26-object-detection.ipynb)
385
  - [Sample video: Urban roundabout with cars and pedestrian (Pexels)](https://www.pexels.com/video/urban-roundabout-with-cars-and-pedestrian-30119018/)
386
  - [OpenVINO Documentation](https://docs.openvino.ai/)
387
  - [NNCF Post-Training Quantization](https://docs.openvino.ai/latest/nncf_ptq_introduction.html)
388
- - [Intel DLStreamer](https://docs.openedgeplatform.intel.com/2026.0/edge-ai-libraries/dlstreamer/index.html)
 
8
  - intel
9
  - yolo
10
  - yolo26
11
+ - detr
12
  - object-classification
13
  - classification
14
  - smart-city
 
26
  | Property | Value |
27
  |---|---|
28
  | **Category** | Object Classification (Traffic Categorization: People / Vehicles) |
29
+ | **Base Model** | [YOLO26](https://docs.ultralytics.com/models/yolo26/) (Ultralytics, default) or [DETR](https://huggingface.co/facebook/detr-resnet-50) (Facebook, alternative) |
30
+ | **Source Framework** | PyTorch (Ultralytics, Hugging Face Transformers) |
31
  | **Supported Precisions** | FP32, FP16, INT8 (mixed-precision) |
32
  | **Inference Engine** | OpenVINO |
33
  | **Hardware** | CPU, GPU, NPU |
 
55
  - **Intersection and Roundabout Monitoring** -- track the mix of pedestrians and vehicles at busy junctions.
56
  - **Trend Analytics** -- aggregate category counts over time to understand traffic patterns.
57
 
58
+ Available variants: `yolo26n`, `yolo26s`, `yolo26m`, `yolo26l`.
59
  Smaller variants (`yolo26n`, `yolo26s`) are recommended for high-FPS edge deployment; larger variants improve recall for small objects.
60
 
61
+ ### Model Selection
62
+
63
+ [DETR](https://huggingface.co/facebook/detr-resnet-50) (DEtection TRansformer) is available as an alternative to YOLO26.
64
+ DETR is a transformer-based, NMS-free detector trained on COCO and released under the Apache-2.0 license.
65
+ The export script embeds DETR normalization, box decoding, and the class remap into the OpenVINO IR, so the DETR model produces the same output layout and class ids as YOLO26.
66
+ The same OpenVINO and DLStreamer samples run either model; select one with the `MODEL` constant at the top of each sample.
67
+
68
+ | Model | Variants | Input Size | Output | License |
69
+ |---|---|---|---|---|
70
+ | YOLO26 (default) | `yolo26n`, `yolo26s`, `yolo26m`, `yolo26l` | 640 x 640 | `[1, 300, 6]` | AGPL-3.0 |
71
+ | DETR | `detr-resnet-50` | 800 x 800 | `[1, 100, 6]` | Apache-2.0 |
72
+
73
+ Choose YOLO26 for maximum throughput on edge devices.
74
+ Choose DETR when a permissively licensed transformer detector is preferred; it is heavier and runs at a lower frame rate.
75
+
76
  ---
77
 
78
  ## Prerequisites
79
 
80
+ Target stack: Intel DLStreamer **2026.3.0 RC1** with the matching OpenVINO GenAI bundle **2026.5.0.0.dev20261030** (OpenVINO Runtime **2026.5.0.dev20261030**).
81
+ Use the [native RC1 setup](../README.md#native-rc1-runtime) before running these samples; this is a development stack, not a stable release.
82
+ See the [device validation matrix](../DEVICE_SUPPORT_MATRIX.md) for measured CPU, GPU, and NPU results.
83
+
84
  - Python 3.11+
85
  - [Install OpenVINO](https://docs.openvino.ai/2026/get-started/install-openvino.html) (latest version)
86
+ - [Install Intel DLStreamer](https://docs.openedgeplatform.intel.com/dev/edge-ai-libraries/dlstreamer/get_started/install/install_guide_ubuntu.html) (latest version)
87
 
88
  Create and activate a Python virtual environment before running the scripts:
89
 
 
111
 
112
  This exports the default **yolo26n** model in **FP16** precision.
113
 
114
+ #### Optional: Select a Different Model, Variant, or Precision
115
 
116
  ```bash
117
+ ./export_and_quantize.sh yolo26n FP32 # full-precision
118
+ ./export_and_quantize.sh yolo26n INT8 # quantized
119
+ ./export_and_quantize.sh yolo26s # larger variant, default FP16
120
+ ./export_and_quantize.sh detr-resnet-50 # DETR alternative, default FP16
121
+ ./export_and_quantize.sh detr-resnet-50 INT8 # DETR quantized
122
  ```
123
 
124
+ The first argument selects the model: any YOLO26 variant (`yolo26n`, `yolo26s`, `yolo26m`, `yolo26l`) or DETR (`detr-resnet-50`).
125
  The second argument selects the precision (`FP32`, `FP16`, `INT8`); the default is **FP16**.
126
 
127
  The script performs the following steps:
128
 
129
+ 1. Installs dependencies (`openvino`, `ultralytics` for YOLO26 or `transformers`, `torch` for DETR; adds `nncf` for INT8).
130
  2. Downloads a sample traffic video (`test_video.mp4`) of an urban roundabout at low resolution (640x360).
131
  3. Downloads the PyTorch weights and exports to OpenVINO IR.
132
  4. *(INT8 only)* Quantizes the model using NNCF post-training quantization.
133
 
134
+ Output files (replace `yolo26n` with the selected model, for example `detr-resnet-50`):
135
 
136
  - `yolo26n_openvino_model/` -- FP32 or FP16 OpenVINO IR model directory.
137
  - `yolo26n_objcls_int8.xml` / `yolo26n_objcls_int8.bin` -- INT8 quantized model *(only when `INT8` is selected)*.
 
157
  YOLO26 is end-to-end (NMS-free), so no manual non-maximum suppression is needed.
158
  Change the `device` string to run on CPU, GPU, or NPU.
159
 
160
+ The full sample is in [openvino_sample.py](openvino_sample.py); run it with `python3 openvino_sample.py` or copy the code below.
161
+
162
+ <!-- sample: openvino_sample.py -->
163
  ```python
164
+ # SPDX-License-Identifier: MIT
165
+ # Copyright (C) Intel Corporation
166
+ #
167
+ # Object Classification: OpenVINO Runtime sample.
168
+ # See README.md for prerequisites and inputs. Run: python3 openvino_sample.py
169
+
170
  import cv2
171
  import numpy as np
172
  import openvino as ov
173
 
174
  CONF_THRESHOLD = 0.4
175
+ # Select the model: "yolo26n" (default) or "detr-resnet-50".
176
+ MODEL = "yolo26n"
177
+ INPUT_SIZE = 800 if MODEL.startswith("detr") else 640
178
 
179
  # Map the traffic-relevant COCO class ids into higher-level city categories.
180
  # People and Vehicles are the two categories tracked for situational awareness.
 
194
  }
195
 
196
  core = ov.Core()
197
+ model = core.read_model(f"{MODEL}_openvino_model/{MODEL}.xml")
198
 
199
  # YOLO26 embeds the 80 COCO class names in rt_info. Ultralytics separates
200
  # multi-word names with underscores (e.g. "traffic_light"), so restore spaces.
 
227
  blob = cv2.cvtColor(blob, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
228
  blob = blob.transpose(2, 0, 1)[np.newaxis, ...] # NCHW
229
 
230
+ # End-to-end output: [1, N, 6] = [x1, y1, x2, y2, confidence, class_id].
231
+ # (N = 300 for YOLO26, 100 for DETR)
232
  output = compiled([blob])[output_port][0]
233
 
234
  sx, sy = width / INPUT_SIZE, height / INPUT_SIZE
 
265
  print(f"Summary: People={totals['People']} Vehicles={totals['Vehicles']}")
266
  print("Saved: output_openvino.mp4")
267
  ```
268
+ <!-- /sample -->
269
 
270
  **Device targets:**
271
 
 
303
 
304
  > **Notes on running this sample:**
305
  >
306
+ > - Use the FP16 IR (`yolo26n_openvino_model/yolo26n.xml` or `detr-resnet-50_openvino_model/detr-resnet-50.xml`). Class names are
307
  > read automatically from the model's embedded `metadata.yaml` by
308
  > DLStreamer 2026.0+ -- no external `labels-file` is required.
309
  > - Export `PYTHONPATH` so the DLStreamer Python module is importable:
 
315
  > /opt/intel/dlstreamer/gstreamer/lib/python3/dist-packages:${PYTHONPATH:-}
316
  > ```
317
 
318
+ The full sample is in [dlstreamer_sample.py](dlstreamer_sample.py); run it with `python3 dlstreamer_sample.py` or copy the code below.
319
+
320
+ <!-- sample: dlstreamer_sample.py -->
321
  ```python
322
+ # SPDX-License-Identifier: MIT
323
+ # Copyright (C) Intel Corporation
324
+ #
325
+ # Object Classification: DLStreamer pipeline sample.
326
+ # See README.md for prerequisites and inputs. Run: python3 dlstreamer_sample.py
327
+
328
  import gi
329
 
330
  gi.require_version("Gst", "1.0")
 
346
  "truck": "Vehicles",
347
  }
348
 
349
+ # Select the model: "yolo26n" (default) or "detr-resnet-50".
350
+ MODEL = "yolo26n"
351
+
352
  # For CPU: change device=GPU to device=CPU.
353
  # For NPU: change device=GPU to device=NPU (batch-size=1, nireq=4 recommended).
354
  # gvawatermark displ-cfg:
 
358
  pipeline_str = (
359
  f"filesrc location={INPUT_VIDEO} ! decodebin3 ! "
360
  "videoconvert ! "
361
+ f"gvadetect model={MODEL}_openvino_model/{MODEL}.xml "
362
  "device=GPU "
363
  "threshold=0.4 ! queue ! "
364
  "gvawatermark "
 
408
  pipeline.set_state(Gst.State.NULL)
409
  print(f"Summary: People={totals['People']} Vehicles={totals['Vehicles']}")
410
  ```
411
+ <!-- /sample -->
412
 
413
  #### Expected Output
414
 
 
429
  ## References
430
 
431
  - [YOLO26 Documentation](https://docs.ultralytics.com/models/yolo26/)
432
+ - [DETR Model Card (facebook/detr-resnet-50)](https://huggingface.co/facebook/detr-resnet-50)
433
+ - [End-to-End Object Detection with Transformers (DETR paper)](https://arxiv.org/abs/2005.12872)
434
  - [OpenVINO YOLO26 Notebook](https://github.com/openvinotoolkit/openvino_notebooks/blob/latest/notebooks/yolov26-optimization/yolov26-object-detection.ipynb)
435
  - [Sample video: Urban roundabout with cars and pedestrian (Pexels)](https://www.pexels.com/video/urban-roundabout-with-cars-and-pedestrian-30119018/)
436
  - [OpenVINO Documentation](https://docs.openvino.ai/)
437
  - [NNCF Post-Training Quantization](https://docs.openvino.ai/latest/nncf_ptq_introduction.html)
438
+ - [Intel DLStreamer](https://docs.openedgeplatform.intel.com/dev/edge-ai-libraries/dlstreamer/index.html)
config.json CHANGED
@@ -3,8 +3,8 @@
3
  "library_name": "openvino",
4
  "pipeline_tag": "object-detection",
5
  "category": "Object Classification (Traffic Categorization: People / Vehicles)",
6
- "base_model": "YOLO26 (Ultralytics)",
7
- "source_framework": "PyTorch (Ultralytics)",
8
  "supported_precisions": [
9
  "FP32",
10
  "FP16",
@@ -18,5 +18,13 @@
18
  ],
19
  "detected_classes": "`person` and vehicle classes grouped into `People` and `Vehicles`",
20
  "hf_repo_id": "Intel/object-classification",
21
- "description": "Object classification use case using YOLO26 to categorize detections into People and Vehicles for traffic situational awareness"
 
 
 
 
 
 
 
 
22
  }
 
3
  "library_name": "openvino",
4
  "pipeline_tag": "object-detection",
5
  "category": "Object Classification (Traffic Categorization: People / Vehicles)",
6
+ "base_model": "YOLO26 (Ultralytics, default) or DETR facebook/detr-resnet-50 (alternative)",
7
+ "source_framework": "PyTorch (Ultralytics, Hugging Face Transformers)",
8
  "supported_precisions": [
9
  "FP32",
10
  "FP16",
 
18
  ],
19
  "detected_classes": "`person` and vehicle classes grouped into `People` and `Vehicles`",
20
  "hf_repo_id": "Intel/object-classification",
21
+ "description": "Object classification use case using YOLO26 (default) or DETR to categorize detections into People and Vehicles for traffic situational awareness",
22
+ "selectable_models": [
23
+ "yolo26n",
24
+ "yolo26s",
25
+ "yolo26m",
26
+ "yolo26l",
27
+ "detr-resnet-50"
28
+ ],
29
+ "default_model": "yolo26n"
30
  }
dlstreamer_sample.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (C) Intel Corporation
3
+ #
4
+ # Object Classification: DLStreamer pipeline sample.
5
+ # See README.md for prerequisites and inputs. Run: python3 dlstreamer_sample.py
6
+
7
+ import gi
8
+
9
+ gi.require_version("Gst", "1.0")
10
+ gi.require_version("GstAnalytics", "1.0")
11
+ from gi.repository import Gst, GLib, GstAnalytics
12
+
13
+ Gst.init([])
14
+
15
+ INPUT_VIDEO = "test_video.mp4"
16
+
17
+ # Traffic-relevant COCO labels grouped into higher-level city categories.
18
+ CATEGORY_BY_LABEL = {
19
+ "person": "People",
20
+ "bicycle": "Vehicles",
21
+ "car": "Vehicles",
22
+ "motorcycle": "Vehicles",
23
+ "bus": "Vehicles",
24
+ "train": "Vehicles",
25
+ "truck": "Vehicles",
26
+ }
27
+
28
+ # Select the model: "yolo26n" (default) or "detr-resnet-50".
29
+ MODEL = "yolo26n"
30
+
31
+ # For CPU: change device=GPU to device=CPU.
32
+ # For NPU: change device=GPU to device=NPU (batch-size=1, nireq=4 recommended).
33
+ # gvawatermark displ-cfg:
34
+ # show-roi=... draws only the traffic-relevant classes (person + vehicles),
35
+ # so non-traffic detections such as handbag/backpack are not boxed.
36
+ # font-scale=1.5 enlarges the label text for better visualization.
37
+ pipeline_str = (
38
+ f"filesrc location={INPUT_VIDEO} ! decodebin3 ! "
39
+ "videoconvert ! "
40
+ f"gvadetect model={MODEL}_openvino_model/{MODEL}.xml "
41
+ "device=GPU "
42
+ "threshold=0.4 ! queue ! "
43
+ "gvawatermark "
44
+ "displ-cfg=show-roi=person:bicycle:car:motorcycle:bus:train:truck,font-scale=2.5 ! "
45
+ "videoconvert ! video/x-raw,format=I420 ! "
46
+ "openh264enc ! h264parse ! "
47
+ "mp4mux ! filesink name=sink location=output_dlstreamer.mp4"
48
+ )
49
+ pipeline = Gst.parse_launch(pipeline_str)
50
+
51
+ totals = {"People": 0, "Vehicles": 0}
52
+
53
+
54
+ def on_buffer(pad, info):
55
+ buf = info.get_buffer()
56
+ rmeta = GstAnalytics.buffer_get_analytics_relation_meta(buf)
57
+ if rmeta is None:
58
+ return Gst.PadProbeReturn.OK
59
+ counts = {"People": 0, "Vehicles": 0}
60
+ idx = 1
61
+ while True:
62
+ ok, od = rmeta.get_od_mtd(idx)
63
+ if not ok:
64
+ break
65
+ label = GLib.quark_to_string(od.get_obj_type())
66
+ category = CATEGORY_BY_LABEL.get(label)
67
+ if category is not None:
68
+ counts[category] += 1
69
+ totals[category] += 1
70
+ idx += 1
71
+ if counts["People"] or counts["Vehicles"]:
72
+ print(f"frame: People={counts['People']} Vehicles={counts['Vehicles']}",
73
+ flush=True)
74
+ return Gst.PadProbeReturn.OK
75
+
76
+
77
+ sink = pipeline.get_by_name("sink")
78
+ sink_pad = sink.get_static_pad("sink")
79
+ sink_pad.add_probe(Gst.PadProbeType.BUFFER, on_buffer)
80
+
81
+ pipeline.set_state(Gst.State.PLAYING)
82
+ bus = pipeline.get_bus()
83
+ bus.timed_pop_filtered(
84
+ Gst.CLOCK_TIME_NONE,
85
+ Gst.MessageType.EOS | Gst.MessageType.ERROR,
86
+ )
87
+ pipeline.set_state(Gst.State.NULL)
88
+ print(f"Summary: People={totals['People']} Vehicles={totals['Vehicles']}")
export_and_quantize.sh CHANGED
@@ -2,11 +2,21 @@
2
  # SPDX-License-Identifier: MIT
3
  # Copyright (C) Intel Corporation
4
  #
5
- # Export a YOLO26 detector to OpenVINO IR for the object-classification use case.
6
  # The accompanying samples group detected objects into higher-level city
7
  # categories (People, Vehicles) for traffic situational awareness.
8
  # Usage: ./export_and_quantize.sh [MODEL_VARIANT] [PRECISION]
9
  # Example: ./export_and_quantize.sh yolo26n FP16
 
 
 
 
 
 
 
 
 
 
10
  #
11
  # Supported precisions:
12
  # FP32 -- Full-precision floating-point weights
@@ -31,12 +41,20 @@ if [[ "${PRECISION}" != "FP32" && "${PRECISION}" != "FP16" && "${PRECISION}" !=
31
  exit 1
32
  fi
33
 
34
- echo "--- Installing dependencies ---"
35
- if [[ "${PRECISION}" == "INT8" ]]; then
36
- pip install -qU openvino nncf ultralytics
37
- else
38
- pip install -qU openvino ultralytics
39
- fi
 
 
 
 
 
 
 
 
40
 
41
  # Ask for approval before downloading models and sample files
42
  echo ""
@@ -62,6 +80,17 @@ else
62
  fi
63
 
64
  echo ""
 
 
 
 
 
 
 
 
 
 
 
65
  echo "--- Downloading sample test video (urban roundabout) ---"
66
  if [[ ! -f test_video.mp4 ]]; then
67
  wget -q -O test_video.mp4 \
@@ -79,14 +108,92 @@ else
79
  EXPORT_LABEL="FP16"
80
  fi
81
 
82
- echo "--- Exporting ${MODEL_NAME} to OpenVINO IR (${EXPORT_LABEL}) ---"
83
- python3 -c "
 
84
  from ultralytics import YOLO
85
 
86
  model = YOLO('${MODEL_NAME}.pt')
87
- model.export(format='openvino', half=${HALF_FLAG}, dynamic=False, imgsz=640)
88
  print('Export complete: ${MODEL_NAME}_openvino_model/')
89
  "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
  if [[ "${PRECISION}" == "INT8" ]]; then
92
  echo "--- Quantizing to INT8 with NNCF ---"
@@ -105,7 +212,7 @@ ok, frame = cap.read()
105
  cap.release()
106
  if not ok:
107
  raise SystemExit('Could not read a calibration frame from test_video.mp4')
108
- img = cv2.resize(frame, (640, 640))
109
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
110
  img = img.transpose(2, 0, 1)[np.newaxis, ...] # NCHW
111
 
@@ -119,6 +226,7 @@ quantized = nncf.quantize(
119
  calibration_dataset,
120
  preset=nncf.QuantizationPreset.MIXED,
121
  subset_size=300,
 
122
  )
123
 
124
  ov.save_model(quantized, '${MODEL_NAME}_objcls_int8.xml')
 
2
  # SPDX-License-Identifier: MIT
3
  # Copyright (C) Intel Corporation
4
  #
5
+ # Export a YOLO26 or DETR detector to OpenVINO IR for the object-classification use case.
6
  # The accompanying samples group detected objects into higher-level city
7
  # categories (People, Vehicles) for traffic situational awareness.
8
  # Usage: ./export_and_quantize.sh [MODEL_VARIANT] [PRECISION]
9
  # Example: ./export_and_quantize.sh yolo26n FP16
10
+ # Example: ./export_and_quantize.sh detr-resnet-50 FP16
11
+ #
12
+ # Supported model variants:
13
+ # yolo26n, yolo26s, yolo26m, yolo26l -- Ultralytics YOLO26 (default)
14
+ # detr-resnet-50 -- Facebook DETR (Hugging Face)
15
+ #
16
+ # DETR is exported end-to-end: ImageNet normalization, softmax,
17
+ # box decoding, and the COCO-91 to COCO-80 class remap are embedded in the
18
+ # graph, so the IR produces the same [1, N, 6] output layout and class ids as
19
+ # YOLO26 and runs with the same OpenVINO and DLStreamer samples.
20
  #
21
  # Supported precisions:
22
  # FP32 -- Full-precision floating-point weights
 
41
  exit 1
42
  fi
43
 
44
+ case "${MODEL_NAME}" in
45
+ yolo26n|yolo26s|yolo26m|yolo26l)
46
+ MODEL_FAMILY="yolo"
47
+ INPUT_SIZE=640
48
+ ;;
49
+ detr-resnet-50)
50
+ MODEL_FAMILY="detr"
51
+ INPUT_SIZE=800
52
+ ;;
53
+ *)
54
+ echo "ERROR: unsupported model '${MODEL_NAME}'. Choose yolo26[n|s|m|l] or detr-resnet-50." >&2
55
+ exit 1
56
+ ;;
57
+ esac
58
 
59
  # Ask for approval before downloading models and sample files
60
  echo ""
 
80
  fi
81
 
82
  echo ""
83
+ echo "--- Installing dependencies ---"
84
+ if [[ "${MODEL_FAMILY}" == "detr" ]]; then
85
+ DEPS=(openvino transformers torch pyyaml opencv-python)
86
+ else
87
+ DEPS=(openvino ultralytics)
88
+ fi
89
+ if [[ "${PRECISION}" == "INT8" ]]; then
90
+ DEPS+=(nncf)
91
+ fi
92
+ pip install -qU "${DEPS[@]}"
93
+
94
  echo "--- Downloading sample test video (urban roundabout) ---"
95
  if [[ ! -f test_video.mp4 ]]; then
96
  wget -q -O test_video.mp4 \
 
108
  EXPORT_LABEL="FP16"
109
  fi
110
 
111
+ if [[ "${MODEL_FAMILY}" == "yolo" ]]; then
112
+ echo "--- Exporting ${MODEL_NAME} to OpenVINO IR (${EXPORT_LABEL}) ---"
113
+ python3 -c "
114
  from ultralytics import YOLO
115
 
116
  model = YOLO('${MODEL_NAME}.pt')
117
+ model.export(format='openvino', half=${HALF_FLAG}, dynamic=False, imgsz=${INPUT_SIZE}, nms=False)
118
  print('Export complete: ${MODEL_NAME}_openvino_model/')
119
  "
120
+ else
121
+ echo "--- Exporting facebook/${MODEL_NAME} to OpenVINO IR (${EXPORT_LABEL}) ---"
122
+ python3 - "${MODEL_NAME}" "${HALF_FLAG}" "${INPUT_SIZE}" <<'PYEXPORT'
123
+ import sys
124
+ from pathlib import Path
125
+
126
+ import openvino as ov
127
+ import torch
128
+ import yaml
129
+ from transformers import DetrForObjectDetection
130
+
131
+ model_name, half_flag, size = sys.argv[1], sys.argv[2] == "True", int(sys.argv[3])
132
+ model_id = f"facebook/{model_name}"
133
+
134
+ # The "no_timm" revision uses the transformers ResNet backbone (no timm dependency).
135
+ detr = DetrForObjectDetection.from_pretrained(model_id, revision="no_timm").eval()
136
+ id2label = detr.config.id2label
137
+ # DETR predicts 91 COCO category ids (with "N/A" gaps) plus a no-object class.
138
+ # Keep the 80 real categories so class ids match YOLO26 (person = 0).
139
+ coco80 = [k for k in sorted(id2label) if id2label[k] != "N/A"]
140
+ assert len(coco80) == 80, f"unexpected label map with {len(coco80)} classes"
141
+
142
+
143
+ class DetrEndToEnd(torch.nn.Module):
144
+ """Input: RGB [0, 1] NCHW. Output: [1, 100, 6] = [x1, y1, x2, y2, conf, class_id] in input pixels."""
145
+
146
+ def __init__(self, model: torch.nn.Module) -> None:
147
+ super().__init__()
148
+ self.model = model
149
+ self.register_buffer("mean", torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1))
150
+ self.register_buffer("std", torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1))
151
+ self.register_buffer("coco80", torch.tensor(coco80))
152
+
153
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
154
+ out = self.model(pixel_values=(x - self.mean) / self.std, return_dict=True)
155
+ probs = out.logits.softmax(-1).index_select(-1, self.coco80)
156
+ conf, cls = probs.max(-1)
157
+ cx, cy, w, h = (out.pred_boxes * size).unbind(-1)
158
+ return torch.stack([cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2, conf, cls.float()], -1)
159
+
160
+
161
+ ov_model = ov.convert_model(
162
+ DetrEndToEnd(detr), example_input=torch.zeros(1, 3, size, size), input=[1, 3, size, size]
163
+ )
164
+ ov_model.outputs[0].get_tensor().set_names({"output0"})
165
+
166
+ names = {i: id2label[k] for i, k in enumerate(coco80)}
167
+ # DLStreamer reads preprocessing and the post-processor type from model_info.
168
+ model_info = {
169
+ "model_type": "YOLO",
170
+ "labels": " ".join(n.replace(" ", "_") for n in names.values()),
171
+ "resize_type": "standard",
172
+ "reverse_input_channels": "YES",
173
+ "scale_values": "255",
174
+ "iou_threshold": "0.7",
175
+ }
176
+ for key, value in model_info.items():
177
+ ov_model.set_rt_info(value, ["model_info", key])
178
+
179
+ out_dir = Path(f"{model_name}_openvino_model")
180
+ out_dir.mkdir(exist_ok=True)
181
+ ov.save_model(ov_model, out_dir / f"{model_name}.xml", compress_to_fp16=half_flag)
182
+ metadata = {
183
+ "description": f"{model_id} exported end-to-end with YOLO26-compatible output",
184
+ "license": "Apache-2.0",
185
+ "task": "detect",
186
+ "batch": 1,
187
+ "imgsz": [size, size],
188
+ "names": names,
189
+ "channels": 3,
190
+ "end2end": True,
191
+ }
192
+ with open(out_dir / "metadata.yaml", "w", encoding="utf-8") as f:
193
+ yaml.safe_dump(metadata, f, sort_keys=False)
194
+ print(f"Export complete: {out_dir}/")
195
+ PYEXPORT
196
+ fi
197
 
198
  if [[ "${PRECISION}" == "INT8" ]]; then
199
  echo "--- Quantizing to INT8 with NNCF ---"
 
212
  cap.release()
213
  if not ok:
214
  raise SystemExit('Could not read a calibration frame from test_video.mp4')
215
+ img = cv2.resize(frame, (${INPUT_SIZE}, ${INPUT_SIZE}))
216
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
217
  img = img.transpose(2, 0, 1)[np.newaxis, ...] # NCHW
218
 
 
226
  calibration_dataset,
227
  preset=nncf.QuantizationPreset.MIXED,
228
  subset_size=300,
229
+ model_type=nncf.ModelType.TRANSFORMER if '${MODEL_FAMILY}' == 'detr' else None,
230
  )
231
 
232
  ov.save_model(quantized, '${MODEL_NAME}_objcls_int8.xml')
openvino_sample.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (C) Intel Corporation
3
+ #
4
+ # Object Classification: OpenVINO Runtime sample.
5
+ # See README.md for prerequisites and inputs. Run: python3 openvino_sample.py
6
+
7
+ import cv2
8
+ import numpy as np
9
+ import openvino as ov
10
+
11
+ CONF_THRESHOLD = 0.4
12
+ # Select the model: "yolo26n" (default) or "detr-resnet-50".
13
+ MODEL = "yolo26n"
14
+ INPUT_SIZE = 800 if MODEL.startswith("detr") else 640
15
+
16
+ # Map the traffic-relevant COCO class ids into higher-level city categories.
17
+ # People and Vehicles are the two categories tracked for situational awareness.
18
+ CATEGORY_BY_CLASS_ID = {
19
+ 0: "People", # person
20
+ 1: "Vehicles", # bicycle
21
+ 2: "Vehicles", # car
22
+ 3: "Vehicles", # motorcycle
23
+ 5: "Vehicles", # bus
24
+ 6: "Vehicles", # train
25
+ 7: "Vehicles", # truck
26
+ }
27
+ # BGR overlay colors for each category.
28
+ CATEGORY_COLORS = {
29
+ "People": (0, 200, 0),
30
+ "Vehicles": (255, 128, 0),
31
+ }
32
+
33
+ core = ov.Core()
34
+ model = core.read_model(f"{MODEL}_openvino_model/{MODEL}.xml")
35
+
36
+ # YOLO26 embeds the 80 COCO class names in rt_info. Ultralytics separates
37
+ # multi-word names with underscores (e.g. "traffic_light"), so restore spaces.
38
+ COCO_NAMES = [
39
+ name.replace("_", " ")
40
+ for name in model.get_rt_info()["model_info"]["labels"].value.split()
41
+ ]
42
+
43
+ # Change device to "GPU" or "NPU" to run on integrated GPU or NPU.
44
+ compiled = core.compile_model(model, "CPU")
45
+ output_port = compiled.output(0)
46
+
47
+ cap = cv2.VideoCapture("test_video.mp4")
48
+ fps = cap.get(cv2.CAP_PROP_FPS) or 30.0
49
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
50
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
51
+ writer = cv2.VideoWriter(
52
+ "output_openvino.mp4", cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height)
53
+ )
54
+
55
+ totals = {"People": 0, "Vehicles": 0}
56
+ frame_idx = 0
57
+ while True:
58
+ ok, frame = cap.read()
59
+ if not ok:
60
+ break
61
+ frame_idx += 1
62
+
63
+ blob = cv2.resize(frame, (INPUT_SIZE, INPUT_SIZE))
64
+ blob = cv2.cvtColor(blob, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
65
+ blob = blob.transpose(2, 0, 1)[np.newaxis, ...] # NCHW
66
+
67
+ # End-to-end output: [1, N, 6] = [x1, y1, x2, y2, confidence, class_id].
68
+ # (N = 300 for YOLO26, 100 for DETR)
69
+ output = compiled([blob])[output_port][0]
70
+
71
+ sx, sy = width / INPUT_SIZE, height / INPUT_SIZE
72
+ counts = {"People": 0, "Vehicles": 0}
73
+ for x1, y1, x2, y2, conf, class_id in output:
74
+ if conf < CONF_THRESHOLD:
75
+ continue
76
+ category = CATEGORY_BY_CLASS_ID.get(int(class_id))
77
+ if category is None:
78
+ continue # not a traffic-relevant object
79
+ counts[category] += 1
80
+ totals[category] += 1
81
+ color = CATEGORY_COLORS[category]
82
+ px1, py1 = int(x1 * sx), int(y1 * sy)
83
+ px2, py2 = int(x2 * sx), int(y2 * sy)
84
+ label = f"{category}: {COCO_NAMES[int(class_id)]} {conf:.2f}"
85
+ cv2.rectangle(frame, (px1, py1), (px2, py2), color, 2)
86
+ cv2.putText(frame, label, (px1, py1 - 5),
87
+ cv2.FONT_HERSHEY_SIMPLEX, 2.0, color, 2)
88
+
89
+ # Overlay the per-category counts for this frame.
90
+ banner = f"People: {counts['People']} Vehicles: {counts['Vehicles']}"
91
+ cv2.rectangle(frame, (0, 0), (width, 60), (0, 0, 0), -1)
92
+ cv2.putText(frame, banner, (15, 45),
93
+ cv2.FONT_HERSHEY_SIMPLEX, 2.0, (255, 255, 255), 2)
94
+
95
+ if frame_idx % 30 == 0:
96
+ print(f"frame {frame_idx}: {banner}", flush=True)
97
+
98
+ writer.write(frame)
99
+
100
+ cap.release()
101
+ writer.release()
102
+ print(f"Summary: People={totals['People']} Vehicles={totals['Vehicles']}")
103
+ print("Saved: output_openvino.mp4")