vagheshpatel commited on
Commit
8505bef
·
verified ·
1 Parent(s): f7ecc4d

Sync person-reidentification from metro-analytics-catalog

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ 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
+ expected_output_dlstreamer.gif filter=lfs diff=lfs merge=lfs -text
37
+ expected_output_openvino.jpg filter=lfs diff=lfs merge=lfs -text
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) Intel Corporation.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE
README.md ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ license_link: LICENSE
4
+ library_name: openvino
5
+ pipeline_tag: image-classification
6
+ tags:
7
+ - openvino
8
+ - intel
9
+ - person-detection
10
+ - person-reidentification
11
+ - re-identification
12
+ - edge-ai
13
+ - metro
14
+ - dlstreamer
15
+ language:
16
+ - en
17
+ ---
18
+
19
+ # Person Re-Identification
20
+
21
+ | Property | Value |
22
+ |---|---|
23
+ | **Category** | Person Detection + Cross-Camera Re-Identification |
24
+ | **Base Model** | [person-detection-retail-0013](https://docs.openvino.ai/2024/omz_models_model_person_detection_retail_0013.html) + [person-reidentification-retail-0287](https://docs.openvino.ai/2024/omz_models_model_person_reidentification_retail_0287.html) (Open Model Zoo) |
25
+ | **Source Framework** | Caffe / PyTorch (Open Model Zoo) |
26
+ | **Supported Precisions** | FP32, FP16 |
27
+ | **Inference Engine** | OpenVINO |
28
+ | **Hardware** | CPU, GPU, NPU |
29
+ | **Detected Class(es)** | Persons (detection) + 256-d appearance embeddings (re-identification) |
30
+
31
+ ---
32
+
33
+ ## Overview
34
+
35
+ Person Re-Identification is a Metro Analytics use case that tracks the same
36
+ individual across multiple camera views.
37
+ Given a reference person seen on one camera, it locates that same person on
38
+ another camera even though the pose, scale, and viewing angle differ.
39
+ Each detected person is compared to the reference by cosine similarity of its
40
+ appearance embedding vector.
41
+
42
+ It uses a two-stage pipeline:
43
+
44
+ - **person-detection-retail-0013** -- detects every person in the scene.
45
+ - **person-reidentification-retail-0287** -- computes a 256-d appearance
46
+ embedding per person that is robust to viewpoint and lighting changes.
47
+
48
+ Unlike face-based matching, re-identification relies on whole-body appearance
49
+ (clothing, build, gait cues), so it works at surveillance distances where faces
50
+ are not clearly visible.
51
+
52
+ To demonstrate cross-camera behaviour from a single downloadable clip, the wide
53
+ surveillance video is treated as two virtual cameras by time window: an earlier
54
+ enrollment window is **Camera A** (where the reference identity is first seen)
55
+ and a later query window is **Camera B** (where the person is re-identified as
56
+ they continue to move through the scene). This emulates a person first seen on
57
+ one camera and later re-identified on another using the same embedding-matching
58
+ logic that links identities across a real multi-camera network.
59
+
60
+ Typical Metro deployments include:
61
+
62
+ - **Multi-Camera Tracking** -- follow a person across cameras in campuses,
63
+ airports, and transit hubs.
64
+ - **Lost-and-Found / Person of Interest** -- locate where a flagged individual
65
+ appears across a camera network.
66
+ - **Journey Analytics** -- reconstruct a person's path through a facility.
67
+ - **Tailgating and Zone Analytics** -- confirm the same person across entry and
68
+ interior cameras.
69
+
70
+ > **Privacy Note:** Person re-identification processes biometric-adjacent
71
+ > appearance data.
72
+ > Ensure your deployment complies with applicable privacy regulations
73
+ > (GDPR, BIPA, etc.) and has proper consent and retention policies in place.
74
+
75
+ ---
76
+
77
+ ## Prerequisites
78
+
79
+ - Python 3.11+
80
+ - [Install OpenVINO](https://docs.openvino.ai/2026/get-started/install-openvino.html) (latest version)
81
+ - [Install Intel DLStreamer](https://docs.openedgeplatform.intel.com/2026.0/edge-ai-libraries/dlstreamer/get_started/install/install_guide_ubuntu.html) (latest version)
82
+
83
+ Create and activate a Python virtual environment before running the scripts:
84
+
85
+ ```bash
86
+ python3 -m venv .venv --system-site-packages
87
+ source .venv/bin/activate
88
+ ```
89
+
90
+ > **Note:** The `--system-site-packages` flag is required so the virtual
91
+ > environment can access the system-installed OpenVINO and DLStreamer Python
92
+ > packages.
93
+
94
+ ---
95
+
96
+ ## Getting Started
97
+
98
+ ### Download Models
99
+
100
+ Run the provided script to download the person detection and re-identification
101
+ models from the Open Model Zoo:
102
+
103
+ ```bash
104
+ chmod +x export_and_quantize.sh
105
+ ./export_and_quantize.sh
106
+ ```
107
+
108
+ The script downloads `person-detection-retail-0013` and
109
+ `person-reidentification-retail-0287` in FP16, downloads the sample surveillance
110
+ video (`test_video.mp4`), and captures a reference person crop (`person_a.jpg`)
111
+ of the most prominent person seen in the Camera A enrollment window.
112
+
113
+ ### OpenVINO Sample
114
+
115
+ The sample below re-identifies the reference person across camera views.
116
+ It loads the captured reference image (`person_a.jpg`, enrolled from Camera A),
117
+ computes its embedding, then scans frames of the Camera B query window.
118
+ In each Camera B frame it detects every person, embeds each one, and keeps the
119
+ person whose similarity to the reference is highest.
120
+ It writes the Camera B frame with the strongest match, drawing a green box only
121
+ on the re-identified person.
122
+ Change the `device` string to run on CPU, GPU, or NPU.
123
+
124
+ ```python
125
+ import cv2
126
+ import numpy as np
127
+ import openvino as ov
128
+
129
+ DETECTION_MODEL = "intel/person-detection-retail-0013/FP16/person-detection-retail-0013.xml"
130
+ REID_MODEL = "intel/person-reidentification-retail-0287/FP16/person-reidentification-retail-0287.xml"
131
+ REFERENCE_IMAGE = "person_a.jpg" # reference identity enrolled from Camera A
132
+ SCENE_VIDEO = "test_video.mp4" # wide feed; a later window acts as Camera B
133
+ CAMERA_B_START_FRAME = 450 # query window begins ~15s into the clip
134
+ CONF_THRESHOLD = 0.6
135
+ MATCH_THRESHOLD = 0.6
136
+
137
+ core = ov.Core()
138
+
139
+ # Change device to "GPU" or "NPU" to run on integrated GPU or NPU.
140
+ det_compiled = core.compile_model(core.read_model(DETECTION_MODEL), "CPU")
141
+ reid_compiled = core.compile_model(core.read_model(REID_MODEL), "CPU")
142
+
143
+ det_input = det_compiled.input(0)
144
+ det_h, det_w = det_input.shape[2], det_input.shape[3]
145
+ reid_input = reid_compiled.input(0)
146
+ reid_h, reid_w = reid_input.shape[2], reid_input.shape[3]
147
+
148
+
149
+ def detect_persons(img):
150
+ h0, w0 = img.shape[:2]
151
+ blob = cv2.resize(img, (det_w, det_h))
152
+ blob = blob.transpose(2, 0, 1)[np.newaxis, ...].astype(np.float32)
153
+ dets = det_compiled([blob])[det_compiled.output(0)][0][0]
154
+ persons = []
155
+ for d in dets:
156
+ if float(d[2]) < CONF_THRESHOLD:
157
+ continue
158
+ x1 = max(0, int(d[3] * w0))
159
+ y1 = max(0, int(d[4] * h0))
160
+ x2 = min(w0, int(d[5] * w0))
161
+ y2 = min(h0, int(d[6] * h0))
162
+ if x2 > x1 and y2 > y1:
163
+ persons.append((x1, y1, x2, y2))
164
+ return persons
165
+
166
+
167
+ def get_embedding(img, bbox):
168
+ x1, y1, x2, y2 = bbox
169
+ crop = img[y1:y2, x1:x2]
170
+ blob = cv2.resize(crop, (reid_w, reid_h))
171
+ blob = blob.transpose(2, 0, 1)[np.newaxis, ...].astype(np.float32)
172
+ emb = reid_compiled([blob])[reid_compiled.output(0)].flatten()
173
+ return emb / (np.linalg.norm(emb) + 1e-9)
174
+
175
+
176
+ # 1. Embed the reference person enrolled from Camera A.
177
+ # person_a.jpg is already a cropped person, so embed the whole image directly
178
+ # (the re-identification model expects a person crop as its input).
179
+ reference = cv2.imread(REFERENCE_IMAGE)
180
+ if reference is None:
181
+ raise SystemExit("Could not read the reference image")
182
+ ref_emb = get_embedding(reference, (0, 0, reference.shape[1], reference.shape[0]))
183
+
184
+ # 2. Scan the Camera B window and keep the frame with the strongest re-id match.
185
+ cap = cv2.VideoCapture(SCENE_VIDEO)
186
+ total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) or 900
187
+ best = {"sim": 0.0, "frame": None, "bbox": None}
188
+ for frame_idx in range(CAMERA_B_START_FRAME, total, 15):
189
+ cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
190
+ ok, frame = cap.read()
191
+ if not ok:
192
+ break
193
+ for bbox in detect_persons(frame):
194
+ sim = float(np.dot(get_embedding(frame, bbox), ref_emb))
195
+ if sim > best["sim"]:
196
+ best = {"sim": sim, "frame": frame.copy(), "bbox": bbox}
197
+ cap.release()
198
+
199
+ # 3. Annotate and save the best Camera B match.
200
+ if best["frame"] is None:
201
+ raise SystemExit("No person detected in the Camera B window")
202
+ frame = best["frame"]
203
+ if best["sim"] >= MATCH_THRESHOLD:
204
+ x1, y1, x2, y2 = best["bbox"]
205
+ cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
206
+ cv2.putText(frame, f"RE-ID {best['sim']:.2f}", (x1, max(15, y1 - 8)),
207
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
208
+ print(f"Re-identified reference person in Camera B, similarity {best['sim']:.4f}")
209
+ else:
210
+ print(f"No matching person found (best similarity {best['sim']:.4f})")
211
+
212
+ cv2.imwrite("output_openvino.jpg", frame)
213
+ print("Saved: output_openvino.jpg")
214
+ ```
215
+
216
+ **Device targets:**
217
+
218
+ - `"CPU"` -- default, works on all Intel platforms.
219
+ - `"GPU"` -- Intel integrated or discrete GPU.
220
+ - `"NPU"` -- Intel NPU; both FP16 models are NPU-compatible.
221
+
222
+ #### Expected Output
223
+
224
+ ![OpenVINO expected output](expected_output_openvino.jpg)
225
+
226
+ ### DLStreamer Sample
227
+
228
+ The pipeline below runs the person detector via `gvadetect` and the
229
+ re-identification model via `gvaclassify` on the video.
230
+ Frames are pulled through an `appsink`, where each detected person's embedding
231
+ is compared to the reference embedding computed from `person_a.jpg`.
232
+ Only persons that match the reference identity are boxed, so the annotated
233
+ `output_dlstreamer.mp4` highlights the same person as they move across the scene
234
+ even when other people are present.
235
+
236
+ > **Notes on running this sample:**
237
+ >
238
+ > - Export `PYTHONPATH` so the DLStreamer Python modules (`gi`, `gstgva`) are
239
+ > importable:
240
+ >
241
+ > ```bash
242
+ > source /opt/intel/openvino_2026/setupvars.sh
243
+ > source /opt/intel/dlstreamer/scripts/setup_dls_env.sh
244
+ > export PYTHONPATH=/opt/intel/dlstreamer/python:\
245
+ > /opt/intel/dlstreamer/gstreamer/lib/python3/dist-packages:${PYTHONPATH:-}
246
+ > ```
247
+ >
248
+ > - The re-identification embedding is attached as a tensor on each person's
249
+ > region-of-interest metadata. Convert the stream to `BGR` **before**
250
+ > `gvadetect`/`gvaclassify` so a downstream format conversion does not strip
251
+ > those tensors before the `appsink` reads them.
252
+
253
+ ```python
254
+ import gi
255
+
256
+ gi.require_version("Gst", "1.0")
257
+ from gi.repository import Gst
258
+
259
+ Gst.init([])
260
+
261
+ import numpy as np
262
+ import cv2
263
+ from gstgva import VideoFrame
264
+
265
+ INPUT_VIDEO = "test_video.mp4"
266
+ REFERENCE_IMAGE = "person_a.jpg"
267
+ OUTPUT_VIDEO = "output_dlstreamer.mp4"
268
+ DETECTION_MODEL = "intel/person-detection-retail-0013/FP16/person-detection-retail-0013.xml"
269
+ REID_MODEL = "intel/person-reidentification-retail-0287/FP16/person-reidentification-retail-0287.xml"
270
+ # For CPU: change "GPU" to "CPU". For NPU: change "GPU" to "NPU".
271
+ DEVICE = "GPU"
272
+ DET_THRESHOLD = 0.6
273
+ MATCH_THRESHOLD = 0.6
274
+
275
+
276
+ def person_embeddings(video_frame):
277
+ """Yield ((x, y, w, h), normalized_embedding) for each classified person."""
278
+ for region in video_frame.regions():
279
+ rect = region.rect()
280
+ emb = None
281
+ for tensor in region.tensors():
282
+ if tensor.is_detection():
283
+ continue
284
+ data = np.array(tensor.data(), dtype=np.float32)
285
+ if data.size >= 256:
286
+ emb = data[:256]
287
+ if emb is None:
288
+ continue
289
+ emb = emb / (np.linalg.norm(emb) + 1e-9)
290
+ yield (int(rect.x), int(rect.y), int(rect.w), int(rect.h)), emb
291
+
292
+
293
+ def run_pipeline(source_desc, on_frame):
294
+ # Convert to BGR before inference so gvaclassify's embedding tensors survive
295
+ # to the appsink (a later format-changing videoconvert would strip them).
296
+ pipeline = Gst.parse_launch(
297
+ f"{source_desc} ! videoconvert ! video/x-raw,format=BGR ! "
298
+ f"gvadetect model={DETECTION_MODEL} device={DEVICE} "
299
+ f"threshold={DET_THRESHOLD} ! queue ! "
300
+ f"gvaclassify model={REID_MODEL} device={DEVICE} ! queue ! "
301
+ "appsink name=sink emit-signals=true sync=false max-buffers=4 drop=false"
302
+ )
303
+ sink = pipeline.get_by_name("sink")
304
+ sink.connect("new-sample", on_frame)
305
+ pipeline.set_state(Gst.State.PLAYING)
306
+ pipeline.get_bus().timed_pop_filtered(
307
+ Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS | Gst.MessageType.ERROR)
308
+ pipeline.set_state(Gst.State.NULL)
309
+
310
+
311
+ # 1. Compute the reference embedding from the enrolled person image.
312
+ # person_a.jpg is already a person crop, so run the re-identification model on
313
+ # the whole frame (inference-region=full-frame) instead of detecting first.
314
+ ref = {"emb": None}
315
+
316
+
317
+ def on_reference(sink):
318
+ sample = sink.emit("pull-sample")
319
+ if sample is None:
320
+ return Gst.FlowReturn.OK
321
+ vf = VideoFrame(sample.get_buffer(), caps=sample.get_caps())
322
+ for tensor in vf.tensors():
323
+ data = np.array(tensor.data(), dtype=np.float32)
324
+ if data.size >= 256:
325
+ emb = data[:256]
326
+ ref["emb"] = emb / (np.linalg.norm(emb) + 1e-9)
327
+ return Gst.FlowReturn.OK
328
+
329
+
330
+ reference_pipeline = Gst.parse_launch(
331
+ f"filesrc location={REFERENCE_IMAGE} ! jpegdec ! videoconvert ! "
332
+ f"video/x-raw,format=BGR ! "
333
+ f"gvainference model={REID_MODEL} device={DEVICE} "
334
+ f"inference-region=full-frame ! queue ! "
335
+ "appsink name=sink emit-signals=true sync=false max-buffers=4 drop=false"
336
+ )
337
+ ref_sink = reference_pipeline.get_by_name("sink")
338
+ ref_sink.connect("new-sample", on_reference)
339
+ reference_pipeline.set_state(Gst.State.PLAYING)
340
+ reference_pipeline.get_bus().timed_pop_filtered(
341
+ Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS | Gst.MessageType.ERROR)
342
+ reference_pipeline.set_state(Gst.State.NULL)
343
+ if ref["emb"] is None:
344
+ raise SystemExit("Could not compute the reference embedding")
345
+ ref_emb = ref["emb"]
346
+
347
+ # 2. Process the video, boxing only persons that match the reference identity.
348
+ writer = {"w": None}
349
+ match_frames = 0
350
+
351
+
352
+ def on_video(sink):
353
+ global match_frames
354
+ sample = sink.emit("pull-sample")
355
+ if sample is None:
356
+ return Gst.FlowReturn.OK
357
+ vf = VideoFrame(sample.get_buffer(), caps=sample.get_caps())
358
+ matches = []
359
+ for (x, y, w, h), emb in person_embeddings(vf):
360
+ similarity = float(np.dot(emb, ref_emb))
361
+ if similarity >= MATCH_THRESHOLD:
362
+ matches.append((x, y, w, h, similarity))
363
+
364
+ with vf.data() as mat:
365
+ frame = mat.copy()
366
+
367
+ if writer["w"] is None:
368
+ frame_h, frame_w = frame.shape[:2]
369
+ structure = sample.get_caps().get_structure(0)
370
+ ok_fr, fps_n, fps_d = structure.get_fraction("framerate")
371
+ fps = fps_n / fps_d if ok_fr and fps_d else 12
372
+ writer["w"] = cv2.VideoWriter(
373
+ OUTPUT_VIDEO, cv2.VideoWriter_fourcc(*"mp4v"), fps, (frame_w, frame_h))
374
+
375
+ for x, y, w, h, similarity in matches:
376
+ cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
377
+ cv2.putText(frame, f"RE-ID {similarity:.2f}", (x, max(15, y - 8)),
378
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
379
+ if matches:
380
+ match_frames += 1
381
+ writer["w"].write(frame)
382
+ return Gst.FlowReturn.OK
383
+
384
+
385
+ run_pipeline(f"filesrc location={INPUT_VIDEO} ! decodebin3", on_video)
386
+ if writer["w"] is not None:
387
+ writer["w"].release()
388
+ print(f"Frames with a re-identified person: {match_frames}", flush=True)
389
+ print(f"Saved: {OUTPUT_VIDEO}", flush=True)
390
+ ```
391
+
392
+ **Device targets:**
393
+
394
+ - `DEVICE = "GPU"` -- default in the sample code.
395
+ - `DEVICE = "CPU"` -- change `"GPU"` to `"CPU"`.
396
+ - `DEVICE = "NPU"` -- change `"GPU"` to `"NPU"`; use `batch-size=1` and `nireq=4` for best NPU utilization.
397
+
398
+ #### Expected Output
399
+
400
+ ![DLStreamer expected output](expected_output_dlstreamer.gif)
401
+
402
+ ---
403
+
404
+ ## License
405
+
406
+ Licensed under the MIT License. See [LICENSE](LICENSE) for details.
407
+
408
+ ## References
409
+
410
+ - [person-detection-retail-0013](https://docs.openvino.ai/2024/omz_models_model_person_detection_retail_0013.html)
411
+ - [person-reidentification-retail-0287](https://docs.openvino.ai/2024/omz_models_model_person_reidentification_retail_0287.html)
412
+ - [Open Model Zoo](https://github.com/openvinotoolkit/open_model_zoo)
413
+ - [OpenVINO Documentation](https://docs.openvino.ai/)
414
+ - [Intel DLStreamer](https://docs.openedgeplatform.intel.com/2026.0/edge-ai-libraries/dlstreamer/index.html)
expected_output_dlstreamer.gif ADDED

Git LFS Details

  • SHA256: d4cb409a0529ac966d27a679c0013686e32ba73c4a197d9ca45b2c854d881ce7
  • Pointer size: 132 Bytes
  • Size of remote file: 6.35 MB
expected_output_openvino.jpg ADDED

Git LFS Details

  • SHA256: 88cd8880c3e472f8fc55e9e70f77d5f0b9a5d45e1c819692ccc41adc6659e3ab
  • Pointer size: 131 Bytes
  • Size of remote file: 324 kB
export_and_quantize.sh ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: MIT
3
+ # Copyright (C) Intel Corporation
4
+ #
5
+ # Download the person detection and person re-identification models from the
6
+ # Open Model Zoo for the person-reidentification use case, download the sample
7
+ # surveillance video, and capture a reference person crop (person_a.jpg) that
8
+ # represents the identity to re-identify across camera views.
9
+ # Usage: ./export_and_quantize.sh
10
+
11
+ set -euo pipefail
12
+
13
+ # Official Open Model Zoo public model storage (versioned, immutable).
14
+ OMZ_BASE="https://storage.openvinotoolkit.org/repositories/open_model_zoo/2023.0/models_bin/1"
15
+
16
+ echo "--- Installing dependencies ---"
17
+ pip install -qU openvino opencv-python numpy
18
+
19
+ # Download both the IR topology (.xml) and weights (.bin) for an OMZ model
20
+ # from the official storage into intel/<model>/<precision>/.
21
+ download_omz_model() {
22
+ local model="$1"
23
+ local precision="$2"
24
+ local dest="intel/${model}/${precision}"
25
+ mkdir -p "${dest}"
26
+ local ext
27
+ for ext in xml bin; do
28
+ if [[ ! -f "${dest}/${model}.${ext}" ]]; then
29
+ wget -q -O "${dest}/${model}.${ext}" \
30
+ "${OMZ_BASE}/${model}/${precision}/${model}.${ext}"
31
+ fi
32
+ done
33
+ }
34
+
35
+ # Ask for approval before downloading models and sample files
36
+ echo ""
37
+ echo "This script will download:"
38
+ echo " - Model weights and/or sample files"
39
+ echo ""
40
+ read -p "Continue with downloads? (yes/no): " APPROVAL
41
+ if [[ "${APPROVAL}" != "yes" ]]; then
42
+ echo "Download cancelled by user."
43
+ exit 0
44
+ fi
45
+ echo ""
46
+
47
+ echo "--- Downloading person-detection-retail-0013 (FP16) ---"
48
+ download_omz_model person-detection-retail-0013 FP16
49
+ echo "Ready: person-detection-retail-0013"
50
+
51
+ echo "--- Downloading person-reidentification-retail-0287 (FP16) ---"
52
+ download_omz_model person-reidentification-retail-0287 FP16
53
+ echo "Ready: person-reidentification-retail-0287"
54
+
55
+ echo "--- Downloading sample surveillance video ---"
56
+ if [[ ! -f test_video.mp4 ]]; then
57
+ wget -q -O test_video.mp4 \
58
+ "https://github.com/open-edge-platform/edge-ai-resources/raw/main/videos/VIRAT_S_000101.mp4"
59
+ echo "Downloaded: test_video.mp4"
60
+ else
61
+ echo "Already present: test_video.mp4"
62
+ fi
63
+
64
+ echo "--- Capturing the reference person from the Camera A enrollment window ---"
65
+ if [[ ! -f person_a.jpg ]]; then
66
+ python3 - <<'PY'
67
+ import cv2
68
+ import numpy as np
69
+ import openvino as ov
70
+
71
+ DET = "intel/person-detection-retail-0013/FP16/person-detection-retail-0013.xml"
72
+ core = ov.Core()
73
+ det = core.compile_model(core.read_model(DET), "CPU")
74
+ inp = det.input(0)
75
+ det_h, det_w = inp.shape[2], inp.shape[3]
76
+
77
+
78
+ def detect_persons(frame, thr=0.6):
79
+ """Return [(x1, y1, x2, y2), ...] for every person detected in the frame."""
80
+ h, w = frame.shape[:2]
81
+ blob = cv2.resize(frame, (det_w, det_h))
82
+ blob = blob.transpose(2, 0, 1)[np.newaxis, ...].astype(np.float32)
83
+ out = det([blob])[det.output(0)][0][0]
84
+ boxes = []
85
+ for d in out:
86
+ if float(d[2]) < thr:
87
+ continue
88
+ x1 = max(0, int(d[3] * w))
89
+ y1 = max(0, int(d[4] * h))
90
+ x2 = min(w, int(d[5] * w))
91
+ y2 = min(h, int(d[6] * h))
92
+ if x2 > x1 and y2 > y1:
93
+ boxes.append((x1, y1, x2, y2))
94
+ return boxes
95
+
96
+
97
+ # Scan the enrollment window (Camera A, the opening seconds) and capture the
98
+ # most prominent person. This person becomes the reference identity that the
99
+ # samples re-identify in the later Camera B query window.
100
+ cap = cv2.VideoCapture("test_video.mp4")
101
+ best = {"crop": None, "area": 0}
102
+ for frame_idx in range(0, 300, 15):
103
+ cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
104
+ ok, frame = cap.read()
105
+ if not ok:
106
+ break
107
+ for x1, y1, x2, y2 in detect_persons(frame):
108
+ area = (x2 - x1) * (y2 - y1)
109
+ if area > best["area"]:
110
+ best["area"] = area
111
+ best["crop"] = frame[y1:y2, x1:x2].copy()
112
+ cap.release()
113
+
114
+ if best["crop"] is None or best["crop"].size == 0:
115
+ raise SystemExit("Could not capture a reference person from the enrollment window")
116
+ cv2.imwrite("person_a.jpg", best["crop"])
117
+ print("Captured person_a.jpg (reference identity from the Camera A enrollment window)")
118
+ PY
119
+ else
120
+ echo "Already present: person_a.jpg"
121
+ fi
122
+
123
+ echo "--- Done ---"
124
+ echo "Detector : intel/person-detection-retail-0013/FP16/person-detection-retail-0013.xml"
125
+ echo "ReID : intel/person-reidentification-retail-0287/FP16/person-reidentification-retail-0287.xml"
126
+ echo "Reference : person_a.jpg (identity captured from the Camera A enrollment window)"
127
+ echo "Scene : test_video.mp4 (wide-area surveillance clip split into two virtual cameras)"