3D Vehicle Detection on a Laptop iGPU

UrbanOmniDetect-2 draws a 3D box around every vehicle from one uncalibrated camera and places it on a top-down map of the road. On the Intel Iris Xe inside a 12th-gen laptop, quantized to INT8 with OpenVINO and with its final layer kept in float, the medium model runs at 33 ms per frame (30 fps), and its box corners stay within 0.4 px of the original model on two traffic cameras.

Luis Condados · · 15 min read Intermediate
UrbanOmniDetect-2 M on a Shanghai crossing: 3D boxes on the camera view and the same vehicles on a top-down map, detector running INT8 on a laptop's Intel Iris Xe.
UrbanOmniDetect-2 M on a Shanghai crossing: 3D boxes on the camera view and the same vehicles on a top-down map, detector running INT8 on a laptop's Intel Iris Xe.

A traffic camera sees cars as flat pictures; this model turns each one into a box with a length, a width and a height, and puts it on a map of the road seen from above, without anyone measuring the camera first.

Dashboard: a Shanghai crossing with a 3D box drawn around each car and bus, and on the right a top-down map of the same road with each vehicle as a coloured rectangle and a short trail behind it
The finished result, running on a laptop’s integrated GPU: 3D boxes on the camera view (left), the same vehicles on a top-down map of the road (right). Footage by Thompson Fang, CC BY [15].

You have met this kind of output already, usually without the 3D part being visible:

  • Traffic counting and classification on city cameras, where a car, a van and a bus need telling apart by size, not only by label.
  • Parking and kerbside monitoring, which needs to know where a vehicle stands on the ground, not where it appears in the picture.
  • Road-safety studies that measure gaps and closing speeds between vehicles, which only make sense on a top-down map.
  • Driver-assistance research, where the same 3D boxes come from a camera on the car itself; the KITTI benchmark [13] that this model trains on is that viewpoint.

The surprise is how little hardware it needs: a recent model that reads 3D shape from one uncalibrated camera runs in real time on the graphics chip built into an ordinary laptop. UrbanOmniDetect-2 M at 640 px, quantized to INT8 with OpenVINO (Intel’s inference toolkit) and with its final layer kept in float, takes a median 33 ms per frame on an Intel Iris Xe (30 fps), 1.74× faster than FP16 on the same chip. Its box corners land within 0.39 px (median) of the original PyTorch model on one camera and 0.50 px on a second it was not calibrated on, and 98.5 to 98.9% of its detections match. These are agreement numbers, not accuracy: neither clip has ground truth.

The model is UrbanOmniDetect-2 by Mehmet Kerem Turkcan [1][2], the follow-up to a CVPR 2026 workshop paper. Its release was timed on an RTX PRO 6000. This post asks the edge question instead: what does it cost on hardware that is already on a desk, the Intel Iris Xe iGPU (an iGPU is the graphics chip inside the processor package, with no memory of its own) in a 12th-generation Core i7 laptop. The same laptop’s RTX 3060 and its CPU serve as the comparisons. It is the same question this site asked of YOLO-NAS and of YOLO26-seg and RF-DETR-Seg, now for a model whose output is geometry.

The two cameras

Both clips are real footage under a Creative Commons Attribution (CC BY) licence, filmed from a footbridge by a fixed camera, and the model’s released training mix lists no YouTube footage [2]:

Footbridge roadShanghai crossing
Scene2+2-lane road with a slip road, suburbanten-lane signalised crossing, bus lane, buses and taxis
SourceKarol Majek [14], 4K, 30 fpsThompson Fang [15], 4K, 25 fps
Used forevery latency number; INT8 calibration (a separate stretch)a second parity check the calibration never saw (at 238 s; the demo shows 50 to 64 s)
Vehicles with a 3D box per frame17.7 on average in the demo, 23 at most29.6 on average in the demo, 34 at most

Every number in this post comes from these two clips. They are the running example: when a section says “the footbridge” or “Shanghai”, it means these frames.

What you are about to see

The video below runs the medium model (M, 21.3 M parameters [2]) quantized to INT8 on the Iris Xe. Watch the left panel for the boxes and the right panel for the top-down map, where each coloured rectangle is a vehicle’s footprint on the road and the line behind it is where it has been.

Footbridge road (17 s, Karol Majek [14]) then the Shanghai crossing (14 s, Thompson Fang [15]), both CC BY, number plates blurred. The detector is UrbanOmniDetect-2 M at 640 px, OpenVINO INT8 on the Iris Xe. Tracking and the offline smoothing that makes the boxes this steady are the upstream renderer’s —refine pass; only the detector is timed. The top-down background is an empty-road image built from the same camera.
1 Camera frameone fixed camera, 1920×1080,no calibration on file2 Detector (timed)UrbanOmniDetect-2 M, INT8,Iris Xe: 33 ms per frame3 Box, class, 8 cornersthe 3D box drawn in the image:4 on the road, 4 on the roof4 Ground cornersthe 4 road-contact cornersof every vehicle5 Ground homographyone 3×3 map, image → road,fitted from the footprints6 Top-down maptracks, trails, empty-roadbackground (offline here)
The pipeline behind the video. Only step 2 is in the latency numbers; steps 5 and 6 come from the upstream renderer [2], with its offline smoothing switched on.
  1. Camera frame. A fixed camera nobody has measured: no focal length, no height, no tilt.
  2. Detector. One forward pass of a YOLO26 network with a pose head (the part of the network that outputs keypoints) [2]. This is the only step timed in this post, at 33 ms per frame on the Iris Xe in INT8.
  3. Box, class, 8 corners. For each road user the network returns a 2D box, one of the 80 everyday object classes of the COCO dataset, and eight keypoints: the corners of its 3D box as they appear in the image, four touching the road and four on the roof [1].
  4. Ground corners. The four road-contact corners of each vehicle are its footprint.
  5. Ground homography. A homography is a 3×3 matrix that maps one plane onto another (here, the road as photographed onto the road seen from above); the homography unit builds one from scratch. Turkcan’s solver starts from a normalised DLT fit (the standard estimate of a homography from point pairs, built step by step here) [4] and refines it over all the footprints under the constraint that each must come out as a rectangle with right-angled corners [1]. Knowing right angles on a plane is enough to recover its shape up to scale [3], which is what removes the need for camera calibration. For a fixed camera it is fitted once for the whole clip.
  6. Top-down map. Every footprint goes through that matrix onto the map. The background is the same camera’s view of the empty road, warped through the same matrix.

The warp in step 6 is the same operation as the bird’s-eye view of a pickleball court in unit 3.5. Drag the court’s corners and watch the top-down view follow; on the road, the four corners come from the vehicles instead of the painted lines.

Try it: the same top-down warp, on a court you can drag

Frame 45000 of "2026.07.25 WD Open … (Gold Medal match)" by pickleball4you, CC BY 3.0.

The speed: 30 fps on the laptop’s own graphics chip

Every row below is the detector’s inference stage alone, at 640 px, as the median of 200 frames of the footbridge clip after 20 warm-up frames, in three separate sessions (the spread between them is under the chart; how the sessions were run is in the reproducibility block). INT8 means the weights and activations are 8-bit integers instead of 16- or 32-bit floats [5], and FP16 or FP32 means 16- or 32-bit floats. “Float head” means everything is INT8 except the network’s final layer, the part that writes out the boxes and corners.

M at 640 px: detector ms per frame 0 40 80 121 161 57.8 ms Iris Xe FP16 33.2 ms Iris Xe INT8, float head 160.9 ms CPU FP32 48.2 ms CPU INT8 4 ms RTX 3060 TensorRT FP16
Median of three sessions; fastest to slowest session: Iris Xe FP16 55.8 to 68.5 ms, Iris Xe INT8 float head 26.1 to 47.1, CPU FP32 156.1 to 165.8, CPU INT8 46.2 to 53.6, RTX 3060 3.9 to 4.0. The Iris Xe INT8 bar is the featured configuration: 33.2 ms is 30 frames per second. The RTX 3060 is the same laptop's discrete GPU, shown for scale.

Read it from the decision you are making. On the iGPU, INT8 with a float head is what crosses the line into real time: 33.2 ms against 57.8 ms for FP16, a 1.74× speed-up (the frame time drops by 43%). The CPU on its own is not far behind in INT8, at 48.2 ms, 3.3× faster than the same CPU in FP32 [9]. The discrete RTX 3060 with TensorRT (NVIDIA’s inference compiler) [11] is in another league at 4.0 ms, which is the reason to buy one, and the reason this post is about the cases where you do not have one.

The model the release was shown with is the largest one, X, at 960 px. On the same Iris Xe it takes 303.9 ms per frame, 3.3 fps, and 20.9 ms on the RTX 3060 with TensorRT. The medium model at 640 px is the one that fits this hardware.

Move the frame rate and flip between a cool and a hot machine to see where each configuration stops keeping up:

Try it: how many cameras per machine

The quality: what INT8 does to the corners

A faster model is only useful if it still puts the corners in the same place. Every quantized or exported model here is compared with the original PyTorch FP32 model on the same frames. A detection matches when there is an FP32 detection of the same class whose box overlaps it by at least half (IoU ≥ 0.5, with the IoU explained here), and corner error is the distance in pixels between matching corners, counted where the FP32 model is confident in that corner.

0.000.250.500.751.000.220.31FP160.960.95INT8, whole network0.390.50INT8, float headfootbridgeShanghai (not used for calibration)median corner error, px
Median corner error against the FP32 model, M at 640 px on the Iris Xe (lower is closer). Quantizing the whole network moves the corners by about 1 px on both cameras; keeping the final layer in float cuts that by more than half. The INT8 calibration frames came from the footbridge clip only.
M @640 on the Iris XeCorner error median / p90Detections matched (recall / precision)
Footbridge, FP160.22 / 0.56 px99.5% / 99.7%
Footbridge, INT8 full0.96 / 3.04 px98.2% / 97.9%
Footbridge, INT8 float head0.39 / 0.98 px98.9% / 98.7%
Shanghai, FP160.31 / 0.53 px99.6% / 99.5%
Shanghai, INT8 full0.95 / 2.64 px97.5% / 95.8%
Shanghai, INT8 float head0.50 / 1.21 px98.5% / 98.2%

The p90 is the error that 90% of corners stay under. Recall here is the share of FP32 detections the quantized model also finds, and precision is the share of its detections that FP32 also made.

The pattern holds on the Shanghai clip, which the calibration never saw: 0.95 px full INT8 against 0.50 px with the float head. It also matches what happened to RF-DETR-Seg’s mask head on this same iGPU, where full INT8 broke the masks outright: the last layer, which writes the geometry, is the one that pays for 8-bit arithmetic. OpenVINO’s quantization guide gives excluding the model’s last layer to preserve accuracy as its example of what ignored_scope is for [7], and the Ultralytics INT8 exporter does the same with the MIXED preset [12], where weights are quantized symmetrically and activations asymmetrically [6][10]. Finding the layer by quantizing one part at a time is the debugging procedure in Nagel et al. [6]. I tested one calibration set (300 frames) and one preset; a different calibration mix or quantization-aware training could close the gap without the float head, and I did not try either.

What this means if you are deploying it

  • One camera at 15 fps runs on a laptop with no graphics card. The Iris Xe takes 33 ms per frame median, 47 ms on a hot day, with the M model in INT8 and its final layer in float. Two cameras fit when the machine runs cool.
  • Keep the final layer in float when you quantize. It costs nothing measurable in speed and halves the corner drift (0.96 → 0.39 px on the footbridge, 0.95 → 0.50 px in Shanghai).
  • Pick the M model at 640 px for this hardware. The release’s X at 960 px takes 304 ms per frame on the Iris Xe (3.3 fps). If the scene has large vehicles close to the camera, X is the one that gets their boxes right (see Limitations), and it needs a discrete GPU: 21 ms on an RTX 3060 with TensorRT.
  • Plan for heat. The iGPU shares a power budget with the CPU, and the same configuration ranged from 26.1 to 47.1 ms across three sessions. Size the camera count on the slow end.
  • Budget for the AGPL. The model’s weights are AGPL-3.0 by their model card, its code by its README (the repository has no LICENSE file), and the Ultralytics library that runs them is AGPL-3.0 too [2][12]. It is a licence whose obligations reach software offered to users over a network. Have that read before you build a product on it. TensorRT, for the discrete-GPU path, is under NVIDIA’s proprietary licence.
  • This does not tell you the accuracy on your road. Every quality number here is agreement with the FP32 model, on two clips with no ground truth. For measured 3D accuracy see the release’s KITTI results [2], and expect your camera to differ.

Limitations & caveats

  • No ground truth. The 98.5 to 98.9% match and the 0.39 to 0.50 px corner error compare the quantized model with the original one. They say the deployment did not change the model; they do not say the model is right. The release reports KITTI 3D accuracy for each size [2]; I did not re-measure it.
  • Large vehicles cut by the frame edge break the M model’s boxes. On the footbridge a bus entering at the right edge got a box covering only its front, and in Shanghai a turning bus leaving at the left got one covering its rear. X at 960 px drew the footbridge bus correctly (all eight corners above 0.62 confidence in a single-frame check). The demo video stops the footbridge clip at 17 s, before the bus, starts the Shanghai clip 8 s into its segment, after one such bus, and draws vehicles touching the frame edge as flat 2D boxes. That editing is deliberate and it hides a real failure.
  • The latency is the detector alone. Preprocessing adds about 1.8 ms and postprocessing 0.3 ms per frame (reported separately in the artifact). Tracking, the ground solve and the offline smoothing that make the video steady were not timed; the upstream renderer’s own counter reported 19.6 to 20.2 fps for detection, tracking and the ground solve together on this iGPU, once per render, while also writing video.
  • The video’s smoothness is offline. It comes from the upstream --refine pass, which uses the whole clip to make each track a rigid box. A live system without it shows more jitter.
  • The top-down map has no scale. Without calibration the ground plane is known up to an unknown scale, so positions are in “car lengths”, not metres. Far from the camera the footprints get unreliable: in the footbridge frame, cars whose image box was about 45 px tall came out at roughly half the median car length on the map.
  • One laptop, one iGPU. Other Iris Xe parts have different execution-unit counts and power limits. In session 1, the INT8 speed-up over FP16 on the iGPU (1.3× to 1.9× across the N, S and M sizes) was smaller than INT8 over FP32 on the CPU (2.1× to 3.5×); I did not test why.
  • Session-to-session drift is large on the iGPU. The featured row ranged from 26.1 to 47.1 ms. The discrete GPU and the CPU stayed within 10%.
  • Near-miss detection is not in here. A first try at measuring time-to-collision between vehicles on the top-down map flagged ordinary braking into a queue as danger, because a constant-speed assumption cannot tell the two apart. A version with measures built for that, on the full five-minute clips, is the next post.

Reproducibility

ParameterValue
CPUIntel Core i7-12700H (14 cores, 20 threads)
iGPUIntel Iris Xe (in the i7-12700H), OpenVINO device GPU.0
dGPUNVIDIA GeForce RTX 3060 Laptop, 6 GB, driver 580.173.02
RAM and OS31 GB; Ubuntu 22.04.5 LTS, kernel 6.8.0-138-generic; on AC power
Library versionsPython 3.12.9, torch 2.14.1+cu130, ultralytics 8.4.61, openvino 2026.4.1, nncf 3.4.0, tensorrt-cu13 10.16.1.11, opencv 5.0.0.93
Model and checkpointUrbanOmniDetect-2 n/s/m/l/x 640 checkpoints, Hugging Face revision be4f69a, AGPL-3.0 per the model card; code at commit caa8537, AGPL-3.0 per its README [2]. Loaded through a two-line inference-only stub, so no upstream code runs during measurement
Exportstock Ultralytics export(format="openvino"/"engine", half=True, imgsz=640 or 960, batch=1, dynamic=False) [12]
QuantizationNNCF post-training, preset MIXED, 300 calibration frames from the footbridge video at 70 s to the end (disjoint from the timed segment), letterboxed like the predictor; “float head” = module 23 (the Pose26 head) in ignored_scope [10]
Precision labelsby execution, not by file: the iGPU plugin’s default inference precision is f16 and the CPU’s is f32 on this processor (no AVX512_BF16) [8][9], both read back from the runtime on this laptop. Hence “iGPU FP16” and “CPU FP32” for the same FP16 IR
DataFootbridge: Karol Majek [14], scaled to 1080p; timing and parity on the first 220 frames (7.3 s) of the segment starting at 26 s. Shanghai: Thompson Fang [15], 1080p; parity on the first 220 frames (8.8 s) from 238 s. Demo: footbridge 26 to 43 s, Shanghai 50 to 64 s
Timing methodUltralytics per-stage profile, inference stage only, median of 200 frames after 20 warm-up frames; square letterbox (rect=False) for every backend; TensorRT time includes the host-to-device copy, PyTorch CUDA is synchronised
Sessions3 sessions on 4 and 5 October 2026 for the featured rows; in the third, each run waited up to 3 minutes for the CPU to cool and logged the iGPU clock (1300 of 1400 MHz); most other rows 2 sessions
Excluded from timingdecode, preprocessing (median ~1.8 ms), postprocessing (~0.3 ms), tracking, ground solve, refinement, rendering
Parityper frame, Hungarian matching on class and IoU ≥ 0.5 against PyTorch FP32 at confidence ≥ 0.25; corners counted where FP32 corner confidence ≥ 0.5
Demo renderingupstream bev_realtime_v2.py --refine --labels with the INT8 IR on the iGPU, composed by scripts/compose.py; plates blurred with open-image-models (MIT); empty-road backgrounds as the per-pixel median of 236 frames (footbridge) and of 360 frames with detected vehicles masked out (Shanghai, where a queue at the red light never clears)

Command, for the featured row:

uv run python scripts/quant_ov.py --ir models/v2m_640_fp16_openvino_model \
  --clip data/clips/karol_calib_1080.mp4 --n 300 --imgsz 640 --ignore-head
uv run python scripts/bench.py --model models/v2m_640_int8head_openvino_model \
  --device intel:gpu.0 --imgsz 640 --clip data/clips/karol_seg_1080.mp4 \
  --frames 200 --warmup 20 --tag ov-igpu-int8head-m640 --session s3

Every number in this post is in output/results_all.md, output/latency*.jsonl or output/parity_*.jsonl in the companion repo, except three that come from the demo renders, which the repo’s scripts regenerate: the cuboid counts per frame and the 45 px car height (label files), and the upstream renderer’s 19.6 to 20.2 fps (its console output).

Further reading

  • The method: Turkcan, Gumaste and Kostic’s paper [1], for how eight corners and a right-angle constraint replace camera calibration, and the KITTI comparison against methods that need it.
  • The geometry underneath: Hartley and Zisserman [3], ch. 1 (a free sample chapter), for why a plane maps to a plane through a 3×3 matrix, and the homography unit on this site for the same idea built step by step, including computing one from four points.
  • Quantization in practice: Nagel et al. [6], §3 and its debugging flow chart, for the standard post-training pipeline and how to find the one layer that breaks under INT8.
  • Related on CondadosAI: YOLO-NAS on a laptop CPU and iGPU · RF-DETR vs YOLO-NAS on the edge · player and ball tracking on an iGPU.

References

[1] Turkcan, M. K., Gumaste, D., & Kostic, Z. (2026). Calibration-Free View-Agnostic Monocular 3D Object Detection for Urban Scenes. Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR) Workshops, pp. 786–795, §3.1 “Overview”, §3.3 “Keypoint-Based 3D Box Prediction”, §3.4 “Bird’s-Eye-View Projection”. openaccess.thecvf.com. The paper’s model is the earlier YOLO11 pose-only version; this post cites it for the corner representation and the ground homography, which the release keeps.

[2] Turkcan, M. K. (2026). UrbanOmniDetect-2: One Network for Detection and Calibration-Free 3D Cuboids from Any Viewpoint. Software and model weights, AGPL-3.0 (declared in the README and the model card; the repository has no LICENSE file). github.com/mkturkcan/urbanomnidetect (commit caa8537, 29 Sep 2026); weights huggingface.co/mehmetkeremturkcan/UrbanOmniDetect-2 (revision be4f69a).

[3] Hartley, R., & Zisserman, A. (2004). Multiple View Geometry in Computer Vision (2nd ed.), ch. 1 “Introduction – a Tour of Multiple View Geometry”, §1.1.1 “Affine and Euclidean Geometry”, p. 4, and §1.2 “Camera projections”, p. 10. Cambridge University Press.

[4] Hartley, R., & Zisserman, A. (2004). Multiple View Geometry in Computer Vision (2nd ed.), ch. 4 “Estimation – 2D Projective Transformations”, §4.1 “The Direct Linear Transformation (DLT) algorithm”, p. 88, and §4.4 “Transformation invariance and normalization”, p. 104. Cambridge University Press.

[5] Jacob, B., Kligys, S., Chen, B., Zhu, M., Tang, M., Howard, A., Adam, H., & Kalenichenko, D. (2018). Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference. Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), pp. 2704–2713, §2.1 “Quantization scheme”. doi:10.1109/CVPR.2018.00286 · arXiv:1712.05877

[6] Nagel, M., Fournarakis, M., Amjad, R. A., Bondarenko, Y., van Baalen, M., & Blankevoort, T. (2021). A White Paper on Neural Network Quantization. arXiv preprint, §2.4.1 “Symmetric vs. asymmetric quantization” (p. 8) and §3.7 “Debugging” (p. 17). arXiv:2106.08295

[7] OpenVINO Toolkit Documentation (2026.4). Basic Quantization Flow. docs.openvino.ai/2026

[8] OpenVINO Toolkit Documentation (2026.4). GPU Device, CPU Device and Precision Control. GPU · CPU · Precision Control

[9] OpenVINO (2026.4.1). GPU plugin default options (src/plugins/intel_gpu/include/intel_gpu/runtime/options.inl, inference_precision default f16) and CPU plugin configuration (src/plugins/intel_cpu/src/config.cpp, f32 unless the CPU has AVX512_BF16), tag 2026.4.1, commit e213a14. github.com/openvinotoolkit/openvino

[10] NNCF (3.4.0). nncf.quantize, QuantizationPreset (MIXED: symmetric weights, asymmetric activations) and IgnoredScope, tag v3.4.0, commit 1761616. github.com/openvinotoolkit/nncf

[11] NVIDIA TensorRT (10.16). NvInfer.h, BuilderFlag::kFP16 (“Enable FP16 layer selection, with FP32 fallback”), tag v10.16. github.com/NVIDIA/TensorRT. The 10.16 developer guide is no longer hosted; the header is the version-pinned source.

[12] Ultralytics (8.4.61). Model Export with Ultralytics YOLO and Pose Estimation, documentation and exporter source at tag v8.4.61 (the OpenVINO INT8 exporter calls nncf.quantize with QuantizationPreset.MIXED and an ignored_scope). AGPL-3.0. docs.ultralytics.com/modes/export · docs.ultralytics.com/tasks/pose

[13] Geiger, A., Lenz, P., Stiller, C., & Urtasun, R. (2013). Vision meets Robotics: The KITTI Dataset. The International Journal of Robotics Research, 32(11), 1231–1237. doi:10.1177/0278364913491297

[14] Majek, K. (2018). 4K Road traffic video for object detection and tracking - free download now! YouTube, Creative Commons Attribution licence. youtube.com/watch?v=MNn9qKG2UFI

[15] Fang, T. (2017). In Recording of Yanan Road East-Tibet Road Middle Crossing (title abridged; the full title opens with a Chinese description). YouTube, Creative Commons Attribution licence. youtube.com/watch?v=O0LyetdH4Lg