<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Geti™ Blog</title>
        <link>https://docs.geti.intel.com/blog</link>
        <description>Geti™ Blog</description>
        <lastBuildDate>Wed, 16 Sep 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Keep the Interaction Local: Rebuilding SAM Annotation with OpenVINO]]></title>
            <link>https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino</link>
            <guid>https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino</guid>
            <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How Geti split MobileSAM inference between native OpenVINO execution and browser workers for predictable interactive segmentation.]]></description>
            <content:encoded><![CDATA[<p><em>How Intel Geti split the Segment Anything Model between native Intel silicon and browser workers to deliver instant, predictable interactive segmentation.</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-goal-frictionless-interactive-segmentation">The Goal: Frictionless Interactive Segmentation<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#the-goal-frictionless-interactive-segmentation" class="hash-link" aria-label="Direct link to The Goal: Frictionless Interactive Segmentation" title="Direct link to The Goal: Frictionless Interactive Segmentation" translate="no">​</a></h2>
<p>When an annotator uses Intel® Geti™ to segment an object, their mental model should be instantaneous: click an object, get an accurate polygon mask, annotate, and move on. They should never have to think about where inference is running.</p>
<p><img decoding="async" loading="lazy" alt="Interactive segmentation with SAM in Geti" src="https://docs.geti.intel.com/assets/images/sam-interactive-segmentation-81b9410ad12ca6f229f569f6420a0267.webp" width="1280" height="595" class="img_ev3q"></p>
<p>To deliver that speed, our guiding philosophy was simple: <strong>keep the interaction local</strong>. Network round-trips for every mouse click introduce latency jitter that destroys the tactile feel of an interactive annotation tool.</p>
<p>Achieving that in production, however, required rethinking how we partition vision transformer workloads between native hardware and web runtimes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-the-initial-architecture-and-why-it-made-sense">1. The Initial Architecture (And Why It Made Sense)<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#1-the-initial-architecture-and-why-it-made-sense" class="hash-link" aria-label="Direct link to 1. The Initial Architecture (And Why It Made Sense)" title="Direct link to 1. The Initial Architecture (And Why It Made Sense)" translate="no">​</a></h2>
<p>In our first implementation, we took the "keep it local" philosophy to its logical extreme: we ran the entire Segment Anything (MobileSAM) pipeline directly inside the client runtime.</p>
<p>Whether running in a desktop browser or our standalone Tauri desktop application, the browser engine owned the entire lifecycle:</p>
<!-- -->
<p>To make this viable in a web UI, our frontend team engineered a multi-threaded client pipeline:</p>
<ul>
<li class=""><strong>Off-Main-Thread Execution:</strong> A shared Web Worker hosted ONNX Runtime Web (<code>ort-web</code>) for both the encoder and decoder.</li>
<li class=""><strong>Comlink Bridging:</strong> Maintained a responsive UI thread by wrapping worker communications in asynchronous RPC-style Comlink calls.</li>
<li class=""><strong>In-Memory Cache:</strong> Once an image was encoded into an embedding vector, users could click multiple objects without ever re-running the encoder or pinging a server.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-the-wall-we-hit-the-webview-reality-check">2. The Wall We Hit (The Webview Reality Check)<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#2-the-wall-we-hit-the-webview-reality-check" class="hash-link" aria-label="Direct link to 2. The Wall We Hit (The Webview Reality Check)" title="Direct link to 2. The Wall We Hit (The Webview Reality Check)" translate="no">​</a></h2>
<p>On paper, this was an elegant client-only architecture. In production, we hit a hard ceiling dictated by client runtime fragmentation.</p>
<p>While Web Workers prevent UI freezing, <strong>they do not reduce the raw computational cost of a Vision Transformer</strong>. Geti targets two distinct environments: collaborative web browsers and packaged Tauri desktop apps. The performance gap between them was staggering:</p>
<table><thead><tr><th>Client Environment</th><th>Execution Path</th><th>Observed Behavior</th></tr></thead><tbody><tr><td><strong>Modern Browser (High-end PC)</strong></td><td>WebGPU / Accelerated WebAssembly</td><td>Fast encoding (300–500 ms). Near-instant workflow.</td></tr><tr><td><strong>Tauri Desktop Webview</strong></td><td>Sandboxed CPU Fallback</td><td>Heavy thread throttling; encoding jumped to <strong>15+ seconds</strong>.</td></tr><tr><td><strong>Low-power Laptop Browser</strong></td><td>Constrained Memory / CPU</td><td>Browser tab memory warnings, thermal throttling, and UI stutter.</td></tr></tbody></table>
<p>The best-case browser run was great, but the worst-case was completely unacceptable. We needed native execution speeds, but sending every prompt click over a network connection to a cloud server would destroy interactivity.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-the-pivot-image-work-vs-prompt-work">3. The Pivot (Image Work vs. Prompt Work)<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#3-the-pivot-image-work-vs-prompt-work" class="hash-link" aria-label="Direct link to 3. The Pivot (Image Work vs. Prompt Work)" title="Direct link to 3. The Pivot (Image Work vs. Prompt Work)" translate="no">​</a></h2>
<p>The breakthrough came when we stopped viewing the pipeline as a binary choice between <em>frontend</em> and <em>backend</em>, and instead categorized the workload by its <strong>interaction frequency</strong>:</p>
<table><thead><tr><th>Workload Type</th><th>Stage</th><th>Characteristics</th><th>Optimal Home</th></tr></thead><tbody><tr><td><strong>Image-Dependent Work</strong></td><td>Encoding</td><td>Heavy ViT compute; executed <strong>once</strong> per image/frame.</td><td><strong>Native Host Engine (OpenVINO)</strong></td></tr><tr><td><strong>Prompt-Dependent Work</strong></td><td>Decoding</td><td>Lightweight matrix math; executed <strong>repeatedly</strong> on user clicks.</td><td><strong>Client Web Worker (WASM / ort-web)</strong></td></tr></tbody></table>
<p>The new split pipeline:</p>
<!-- -->
<p>Because images already reside on the backend (or in local desktop storage), the UI does not upload raw pixels. It simply requests an embedding by image ID.</p>
<!-- -->
<p>Crucially, in Geti's Tauri desktop application, the "backend" is simply a <strong>local native sidecar process</strong>. The architecture is identical whether running against a cloud server or a local desktop binary: native silicon execution outside the webview sandbox.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-how-we-built-it-frontend--backend-in-tandem">4. How We Built It (Frontend &amp; Backend in Tandem)<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#4-how-we-built-it-frontend--backend-in-tandem" class="hash-link" aria-label="Direct link to 4. How We Built It (Frontend &amp; Backend in Tandem)" title="Direct link to 4. How We Built It (Frontend &amp; Backend in Tandem)" translate="no">​</a></h2>
<p>Splitting a neural network across process boundaries required both engineering teams to solve hard systems problems simultaneously.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-backend-flexing-intel-silicon-with-openvino">The Backend: Flexing Intel® Silicon with OpenVINO™<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#the-backend-flexing-intel-silicon-with-openvino" class="hash-link" aria-label="Direct link to The Backend: Flexing Intel® Silicon with OpenVINO™" title="Direct link to The Backend: Flexing Intel® Silicon with OpenVINO™" translate="no">​</a></h3>
<p>Our backend and AI engineers built a native inference service optimized for Intel platforms:</p>
<ul>
<li class=""><strong>Dynamic Hardware Targeting:</strong> Using OpenVINO's unified API and <code>AUTO</code> device plugin, the backend seamlessly targets Intel Core™ CPUs, integrated Arc™ GPUs, or dedicated NPUs without code branching.</li>
<li class=""><strong>Hybrid Core Scheduling:</strong> Modern Intel CPUs feature a mix of Performance cores (P-cores) and Efficient cores (E-cores). By setting OpenVINO’s performance mode to <code>LATENCY</code>, the engine optimizes thread scheduling so heavy ViT encoding finishes rapidly without starving companion OS tasks.</li>
<li class=""><strong>Lean Memory Lifecycle:</strong> In a desktop sidecar or containerized environment, models cannot hoard VRAM. We utilized <strong>OpenVINO Compiled-Model Caching</strong> (<code>ov::cache_dir</code>) to store compiled binaries on disk, keeping model weights ready while creating and releasing individual <code>ov::InferRequest</code> instances per job to return execution memory immediately to the OS.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-frontend-high-performance-client-orchestration">The Frontend: High-Performance Client Orchestration<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#the-frontend-high-performance-client-orchestration" class="hash-link" aria-label="Direct link to The Frontend: High-Performance Client Orchestration" title="Direct link to The Frontend: High-Performance Client Orchestration" translate="no">​</a></h3>
<p>Meanwhile, our frontend team rebuilt the client runtime to ingest and manage external embeddings without dropping frames:</p>
<ul>
<li class=""><strong>Zero-Copy Memory Pipelines:</strong> Receiving multi-megabyte binary payloads can trigger severe garbage collection churn. The frontend streams raw <code>safetensors</code> buffers and transfers them into Comlink Web Workers via transferable <code>ArrayBuffer</code> objects, completely bypassing structured-clone overhead.</li>
<li class=""><strong>Dual-Tier State Machines:</strong> Using TanStack Query, the client separates <em>execution lifecycles</em> from <em>data lifecycles</em>. Decoder workers stay alive across project navigation, while heavy 4 MiB embedding tensors are evicted from memory after 60 seconds of inactivity.</li>
<li class=""><strong>Canvas Coordinate Parity:</strong> OpenCV WebAssembly handles polygon generation and letterbox aspect-ratio math directly on the client canvas thread, ensuring generated masks lock precisely to user cursor clicks.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-contract-geometry-and-precision">The Contract: Geometry and Precision<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#the-contract-geometry-and-precision" class="hash-link" aria-label="Direct link to The Contract: Geometry and Precision" title="Direct link to The Contract: Geometry and Precision" translate="no">​</a></h3>
<p>To prevent spatial drift between two different runtimes, the backend serializes the embedding with strict geometry headers (original dimensions, resized dimensions, and padding offsets).</p>
<p>While quantizing to <strong>Float16</strong> would have halved the payload from 4 MiB down to 2 MiB, early evaluations revealed numerical instability in MobileSAM's boundary precision under FP16. We prioritized deterministic mask quality and kept the contract at <strong>Float32</strong>, using gzip/brotli transport compression to minimize wire transfer times.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-the-results--the-takeaway">5. The Results &amp; The Takeaway<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#5-the-results--the-takeaway" class="hash-link" aria-label="Direct link to 5. The Results &amp; The Takeaway" title="Direct link to 5. The Results &amp; The Takeaway" translate="no">​</a></h2>
<p>Moving the encoder to native OpenVINO eliminated the wild performance variance of browser-side ViT execution:</p>
<table><thead><tr><th>Platform &amp; Device</th><th>Runtime Path</th><th>Mean Encoder Inference Time</th></tr></thead><tbody><tr><td><strong>Intel® Core™ (Tiger Lake)</strong></td><td>OpenVINO Native CPU</td><td><strong>439.26 ms</strong></td></tr><tr><td><strong>Intel® Core™ Ultra (Panther Lake)</strong></td><td>OpenVINO Native Intel® GPU</td><td><strong>51.47 ms</strong></td></tr></tbody></table>
<blockquote>
<p><em>Note: Benchmarks represent pure MobileSAM encoder execution time on representative testbeds, excluding I/O, serialization, and network transfer.</em></p>
</blockquote>
<p>Put next to the worst-case webview behavior from before, the difference is hard to miss:</p>
<!-- -->
<p>On Tiger Lake CPU, native execution delivers rock-solid consistency matching the best-case browser runs. On next-generation Panther Lake integrated graphics, encoding drops to <strong>~51 ms</strong>—fast enough to feel instantaneous.</p>
<p>Once that single embedding reaches the client, every click prompt, negative point, and boundary edit runs locally inside the browser with zero network lag.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-architectural-lesson">The Architectural Lesson<a href="https://docs.geti.intel.com/blog/2026/09/16/rebuilding-sam-with-openvino#the-architectural-lesson" class="hash-link" aria-label="Direct link to The Architectural Lesson" title="Direct link to The Architectural Lesson" translate="no">​</a></h2>
<p>High-performance AI web applications do not need to be 100% cloud-hosted or 100% client-side. The key is knowing what kind of work you are scheduling:</p>
<blockquote>
<p><strong>Move the expensive preparation closer to native compute.</strong><br>
<strong>Keep the repeated interaction close to the user.</strong></p>
</blockquote>]]></content:encoded>
            <category>engineering</category>
            <category>openvino</category>
            <category>segmentation</category>
            <category>SAM</category>
            <category>ONNX</category>
        </item>
        <item>
            <title><![CDATA[Welcome to the Geti engineering blog]]></title>
            <link>https://docs.geti.intel.com/blog/2026/09/16/welcome-to-geti</link>
            <guid>https://docs.geti.intel.com/blog/2026/09/16/welcome-to-geti</guid>
            <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Engineering notes on the systems, models, and tooling behind Geti.]]></description>
            <content:encoded><![CDATA[<p>Welcome to the Geti engineering blog. We will share the technical decisions, implementation details, performance investigations, and lessons learned while building production-ready computer vision systems.</p>
<p>Expect posts on model optimization, OpenVINO integration, browser and native runtimes, data workflows, and the engineering tradeoffs that shape Geti. Each post will focus on the problem, the approach, and what we learned in production.</p>]]></content:encoded>
            <category>geti</category>
            <category>engineering</category>
        </item>
    </channel>
</rss>