Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"Building a Vanilla JavaScript Application","local":"building-a-vanilla-javascript-application","sections":[{"title":"Step 1: HTML and CSS setup","local":"step-1-html-and-css-setup","sections":[],"depth":2},{"title":"Step 2: JavaScript setup","local":"step-2-javascript-setup","sections":[],"depth":2},{"title":"Step 3: Create an object detection pipeline","local":"step-3-create-an-object-detection-pipeline","sections":[],"depth":2},{"title":"Step 4: Create the image uploader","local":"step-4-create-the-image-uploader","sections":[],"depth":2},{"title":"Step 5: Run the model","local":"step-5-run-the-model","sections":[],"depth":2},{"title":"Step 6: Render the boxes","local":"step-6-render-the-boxes","sections":[],"depth":2}],"depth":1}"> | |
| <link href="/docs/transformers.js/pr_1649/en/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/entry/start.5f753a22.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/scheduler.6efaaf90.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/singletons.c0807d75.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/paths.c5938264.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/entry/app.db3dfcb7.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/preload-helper.1d8e1e5d.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/index.eb3e1f0f.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/nodes/0.1b727385.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/each.e59479a4.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/nodes/40.6c368179.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/Tip.292c2c3d.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/MermaidChart.svelte_svelte_type_style_lang.16f13047.js"> | |
| <link rel="modulepreload" href="/docs/transformers.js/pr_1649/en/_app/immutable/chunks/CodeBlock.72c8dd07.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{"title":"Building a Vanilla JavaScript Application","local":"building-a-vanilla-javascript-application","sections":[{"title":"Step 1: HTML and CSS setup","local":"step-1-html-and-css-setup","sections":[],"depth":2},{"title":"Step 2: JavaScript setup","local":"step-2-javascript-setup","sections":[],"depth":2},{"title":"Step 3: Create an object detection pipeline","local":"step-3-create-an-object-detection-pipeline","sections":[],"depth":2},{"title":"Step 4: Create the image uploader","local":"step-4-create-the-image-uploader","sections":[],"depth":2},{"title":"Step 5: Run the model","local":"step-5-run-the-model","sections":[],"depth":2},{"title":"Step 6: Render the boxes","local":"step-6-render-the-boxes","sections":[],"depth":2}],"depth":1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg></button></div> </div> <h1 class="relative group"><a id="building-a-vanilla-javascript-application" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#building-a-vanilla-javascript-application"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Building a Vanilla JavaScript Application</span></h1> <p data-svelte-h="svelte-124rffi">In this tutorial, you’ll build a simple web application that detects objects in images using Transformers.js! To follow along, all you need is a code editor, a browser, and a simple server (e.g., VS Code Live Server).</p> <p data-svelte-h="svelte-10r3y0k">Here’s how it works: the user clicks “Upload image” and selects an image using an input dialog. After analysing the image with an object detection model, the predicted bounding boxes are overlaid on top of the image, like this:</p> <p data-svelte-h="svelte-13hi3r9"><img src="https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/js-detection-interence-zebra.png" alt="Demo"></p> <p data-svelte-h="svelte-1tlxmzn">Useful links:</p> <ul data-svelte-h="svelte-111pywj"><li><a href="https://huggingface.co/spaces/Scrimba/vanilla-js-object-detector" rel="nofollow">Demo site</a></li> <li><a href="https://github.com/huggingface/transformers.js-examples/tree/main/vanilla-js" rel="nofollow">Source code</a></li></ul> <h2 class="relative group"><a id="step-1-html-and-css-setup" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-1-html-and-css-setup"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 1: HTML and CSS setup</span></h2> <p data-svelte-h="svelte-1ro6f4o">Before we start building with Transformers.js, we first need to lay the groundwork with some markup and styling. Create an <code>index.html</code> file with a basic HTML skeleton, and add the following <code><main></code> tag to the <code><body></code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-tag"><<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span> | |
| <span class="hljs-tag"><<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"custom-file-upload"</span>></span> | |
| <span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"file-upload"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">accept</span>=<span class="hljs-string">"image/*"</span> /></span> | |
| <span class="hljs-tag"><<span class="hljs-name">img</span> | |
| <span class="hljs-attr">class</span>=<span class="hljs-string">"upload-icon"</span> | |
| <span class="hljs-attr">src</span>=<span class="hljs-string">"https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/upload-icon.png"</span> | |
| /></span> | |
| Upload image | |
| <span class="hljs-tag"></<span class="hljs-name">label</span>></span> | |
| <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"image-container"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span> | |
| <span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"status"</span>></span><span class="hljs-tag"></<span class="hljs-name">p</span>></span> | |
| <span class="hljs-tag"></<span class="hljs-name">main</span>></span><!-- HTML_TAG_END --></pre></div> <details data-svelte-h="svelte-m0rku7"><summary>Click here to see a breakdown of this markup.</summary> <p>We’re adding an <code><input></code> element with <code>type="file"</code> that accepts images. This allows the user to select an image from their local file system using a popup dialog. The default styling for this element looks quite bad, so let’s add some styling. The easiest way to achieve this is to wrap the <code><input></code> element in a <code><label></code>, hide the input, and then style the label as a button.</p> <p>We’re also adding an empty <code><div></code> container for displaying the image, plus an empty <code><p></code> tag that we’ll use to give status updates to the user while we download and run the model, since both of these operations take some time.</p></details> <p data-svelte-h="svelte-1oz6lja">Next, add the following CSS rules in a <code>style.css</code> file and link it to the HTML:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-selector-tag">html</span>, | |
| <span class="hljs-selector-tag">body</span> { | |
| <span class="hljs-attribute">font-family</span>: Arial, Helvetica, sans-serif; | |
| } | |
| <span class="hljs-selector-class">.container</span> { | |
| <span class="hljs-attribute">margin</span>: <span class="hljs-number">40px</span> auto; | |
| <span class="hljs-attribute">width</span>: <span class="hljs-built_in">max</span>(<span class="hljs-number">50vw</span>, <span class="hljs-number">400px</span>); | |
| <span class="hljs-attribute">display</span>: flex; | |
| <span class="hljs-attribute">flex-direction</span>: column; | |
| <span class="hljs-attribute">align-items</span>: center; | |
| } | |
| <span class="hljs-selector-class">.custom-file-upload</span> { | |
| <span class="hljs-attribute">display</span>: flex; | |
| <span class="hljs-attribute">align-items</span>: center; | |
| <span class="hljs-attribute">gap</span>: <span class="hljs-number">10px</span>; | |
| <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid black; | |
| <span class="hljs-attribute">padding</span>: <span class="hljs-number">8px</span> <span class="hljs-number">16px</span>; | |
| <span class="hljs-attribute">cursor</span>: pointer; | |
| <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">6px</span>; | |
| } | |
| <span class="hljs-selector-id">#file-upload</span> { | |
| <span class="hljs-attribute">display</span>: none; | |
| } | |
| <span class="hljs-selector-class">.upload-icon</span> { | |
| <span class="hljs-attribute">width</span>: <span class="hljs-number">30px</span>; | |
| } | |
| <span class="hljs-selector-id">#image-container</span> { | |
| <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; | |
| <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>; | |
| <span class="hljs-attribute">position</span>: relative; | |
| } | |
| <span class="hljs-selector-id">#image-container</span> > <span class="hljs-selector-tag">img</span> { | |
| <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; | |
| }<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-9b3nck">Here’s how the UI looks at this point:</p> <p data-svelte-h="svelte-mwib6l"><img src="https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/js-detection-btn.png" alt="Demo"></p> <h2 class="relative group"><a id="step-2-javascript-setup" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-2-javascript-setup"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 2: JavaScript setup</span></h2> <p data-svelte-h="svelte-k9jxb8">With the <em>boring</em> part out of the way, let’s start writing some JavaScript code! Create a file called <code>index.js</code> and link to it in <code>index.html</code> by adding the following to the end of the <code><body></code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./index.js"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><!-- HTML_TAG_END --></pre></div> <blockquote class="tip"><p data-svelte-h="svelte-kr58bn">The <code>type="module"</code> attribute is important, as it turns our file into a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" rel="nofollow">JavaScript module</a>, meaning that we’ll be able to use imports and exports.</p></blockquote> <p data-svelte-h="svelte-mqvw0e">Moving into <code>index.js</code>, let’s import Transformers.js by adding the following line to the top of the file:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> { | |
| pipeline, | |
| env, | |
| } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://cdn.jsdelivr.net/npm/@huggingface/transformers"</span>;<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1cxz7vo">Since we will be downloading the model from the Hugging Face Hub, we can skip the local model check by setting:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->env.<span class="hljs-property">allowLocalModels</span> = <span class="hljs-literal">false</span>;<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-2hgpai">Next, let’s create references to the various DOM elements we will access later:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">const</span> fileUpload = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">"file-upload"</span>); | |
| <span class="hljs-keyword">const</span> imageContainer = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">"image-container"</span>); | |
| <span class="hljs-keyword">const</span> status = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">"status"</span>);<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="step-3-create-an-object-detection-pipeline" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-3-create-an-object-detection-pipeline"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 3: Create an object detection pipeline</span></h2> <p data-svelte-h="svelte-1d20pgp">We’re finally ready to create our object detection pipeline! As a reminder, a <a href="../pipelines">pipeline</a>. is a high-level interface provided by the library to perform a specific task. In our case, we will instantiate an object detection pipeline with the <code>pipeline()</code> helper function.</p> <p data-svelte-h="svelte-4x6koj">Since this can take some time (especially the first time when we have to download the ~40MB model), we first update the <code>status</code> paragraph so that the user knows that we’re about to load the model.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->status.<span class="hljs-property">textContent</span> = <span class="hljs-string">"Loading model..."</span>;<!-- HTML_TAG_END --></pre></div> <blockquote class="tip"><p data-svelte-h="svelte-g1c7oq">To keep this tutorial simple, we’ll be loading and running the model in the main (UI) thread. This is not recommended for production applications, since the UI will freeze when we’re performing these actions. This is because JavaScript is a single-threaded language. To overcome this, you can use a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers" rel="nofollow">web worker</a> to download and run the model in the background. However, we’re not going to do cover that in this tutorial…</p></blockquote> <p data-svelte-h="svelte-nzqjt5">We can now call the <code>pipeline()</code> function that we imported at the top of our file, to create our object detection pipeline:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">const</span> detector = <span class="hljs-keyword">await</span> <span class="hljs-title function_">pipeline</span>(<span class="hljs-string">"object-detection"</span>, <span class="hljs-string">"Xenova/detr-resnet-50"</span>);<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-eu4w8s">We’re passing two arguments into the <code>pipeline()</code> function: (1) task and (2) model.</p> <ol data-svelte-h="svelte-1fsg0h3"><li><p>The first tells Transformers.js what kind of task we want to perform. In our case, that is <code>object-detection</code>, but there are many other tasks that the library supports, including <code>text-generation</code>, <code>sentiment-analysis</code>, <code>summarization</code>, or <code>automatic-speech-recognition</code>. See <a href="https://huggingface.co/docs/transformers.js/pipelines#tasks" rel="nofollow">here</a> for the full list.</p></li> <li><p>The second argument specifies which model we would like to use to solve the given task. We will use <a href="https://huggingface.co/Xenova/detr-resnet-50" rel="nofollow"><code>Xenova/detr-resnet-50</code></a>, as it is a relatively small (~40MB) but powerful model for detecting objects in an image.</p></li></ol> <p data-svelte-h="svelte-1qhlioo">Once the function returns, we’ll tell the user that the app is ready to be used.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->status.<span class="hljs-property">textContent</span> = <span class="hljs-string">"Ready"</span>;<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="step-4-create-the-image-uploader" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-4-create-the-image-uploader"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 4: Create the image uploader</span></h2> <p data-svelte-h="svelte-1s0f9r2">The next step is to support uploading/selection of images. To achieve this, we will listen for “change” events from the <code>fileUpload</code> element. In the callback function, we use a <code>FileReader()</code> to read the contents of the image if one is selected (and nothing otherwise).</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->fileUpload.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">"change"</span>, <span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) { | |
| <span class="hljs-keyword">const</span> file = e.<span class="hljs-property">target</span>.<span class="hljs-property">files</span>[<span class="hljs-number">0</span>]; | |
| <span class="hljs-keyword">if</span> (!file) { | |
| <span class="hljs-keyword">return</span>; | |
| } | |
| <span class="hljs-keyword">const</span> reader = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FileReader</span>(); | |
| <span class="hljs-comment">// Set up a callback when the file is loaded</span> | |
| reader.<span class="hljs-property">onload</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">e2</span>) { | |
| imageContainer.<span class="hljs-property">innerHTML</span> = <span class="hljs-string">""</span>; | |
| <span class="hljs-keyword">const</span> image = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">"img"</span>); | |
| image.<span class="hljs-property">src</span> = e2.<span class="hljs-property">target</span>.<span class="hljs-property">result</span>; | |
| imageContainer.<span class="hljs-title function_">appendChild</span>(image); | |
| <span class="hljs-comment">// detect(image); // Uncomment this line to run the model</span> | |
| }; | |
| reader.<span class="hljs-title function_">readAsDataURL</span>(file); | |
| });<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1lk01wa">Once the image has been loaded into the browser, the <code>reader.onload</code> callback function will be invoked. In it, we append the new <code><img></code> element to the <code>imageContainer</code> to be displayed to the user.</p> <p data-svelte-h="svelte-4ka4xl">Don’t worry about the <code>detect(image)</code> function call (which is commented out) - we will explain it later! For now, try to run the app and upload an image to the browser. You should see your image displayed under the button like this:</p> <p data-svelte-h="svelte-16s7klb"><img src="https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/js-detection-btn-img.png" alt="Demo"></p> <h2 class="relative group"><a id="step-5-run-the-model" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-5-run-the-model"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 5: Run the model</span></h2> <p data-svelte-h="svelte-17edfdz">We’re finally ready to start interacting with Transformers.js! Let’s uncomment the <code>detect(image)</code> function call from the snippet above. Then we’ll define the function itself:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">detect</span>(<span class="hljs-params">img</span>) { | |
| status.<span class="hljs-property">textContent</span> = <span class="hljs-string">"Analysing..."</span>; | |
| <span class="hljs-keyword">const</span> output = <span class="hljs-keyword">await</span> <span class="hljs-title function_">detector</span>(img.<span class="hljs-property">src</span>, { | |
| <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.5</span>, | |
| <span class="hljs-attr">percentage</span>: <span class="hljs-literal">true</span>, | |
| }); | |
| status.<span class="hljs-property">textContent</span> = <span class="hljs-string">""</span>; | |
| <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"output"</span>, output); | |
| <span class="hljs-comment">// ...</span> | |
| }<!-- HTML_TAG_END --></pre></div> <blockquote class="tip"><p data-svelte-h="svelte-2c69hg">NOTE: The <code>detect</code> function needs to be asynchronous, since we’ll <code>await</code> the result of the the model.</p></blockquote> <p data-svelte-h="svelte-8pzcmm">Once we’ve updated the <code>status</code> to “Analysing”, we’re ready to perform <em>inference</em>, which simply means to run the model with some data. This is done via the <code>detector()</code> function that was returned from <code>pipeline()</code>. The first argument we’re passing is the image data (<code>img.src</code>).</p> <p data-svelte-h="svelte-vbn04e">The second argument is an options object:</p> <ul data-svelte-h="svelte-1flghaj"><li>We set the <code>threshold</code> property to <code>0.5</code>. This means that we want the model to be at least 50% confident before claiming it has detected an object in the image. The lower the threshold, the more objects it’ll detect (but may misidentify objects); the higher the threshold, the fewer objects it’ll detect (but may miss objects in the scene).</li> <li>We also specify <code>percentage: true</code>, which means that we want the bounding box for the objects to be returned as percentages (instead of pixels).</li></ul> <p data-svelte-h="svelte-vz1vzo">If you now try to run the app and upload an image, you should see the following output logged to the console:</p> <p data-svelte-h="svelte-1e4bl98"><img src="https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/js-detection-console.png" alt="Demo"></p> <p data-svelte-h="svelte-ey5r3r">In the example above, we uploaded an image of two elephants, so the <code>output</code> variable holds an array with two objects, each containing a <code>label</code> (the string “elephant”), a <code>score</code> (indicating the model’s confidence in its prediction) and a <code>box</code> object (representing the bounding box of the detected entity).</p> <h2 class="relative group"><a id="step-6-render-the-boxes" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-6-render-the-boxes"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 6: Render the boxes</span></h2> <p data-svelte-h="svelte-xglmdw">The final step is to display the <code>box</code> coordinates as rectangles around each of the elephants.</p> <p data-svelte-h="svelte-6b76js">At the end of our <code>detect()</code> function, we’ll run the <code>renderBox</code> function on each object in the <code>output</code> array, using <code>.forEach()</code>.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->output.<span class="hljs-title function_">forEach</span>(renderBox);<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-88zjgn">Here’s the code for the <code>renderBox()</code> function with comments to help you understand what’s going on:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment">// Render a bounding box and label on the image</span> | |
| <span class="hljs-keyword">function</span> <span class="hljs-title function_">renderBox</span>(<span class="hljs-params">{ box, label }</span>) { | |
| <span class="hljs-keyword">const</span> { xmax, xmin, ymax, ymin } = box; | |
| <span class="hljs-comment">// Generate a random color for the box</span> | |
| <span class="hljs-keyword">const</span> color = | |
| <span class="hljs-string">"#"</span> + | |
| <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">floor</span>(<span class="hljs-title class_">Math</span>.<span class="hljs-title function_">random</span>() * <span class="hljs-number">0xffffff</span>) | |
| .<span class="hljs-title function_">toString</span>(<span class="hljs-number">16</span>) | |
| .<span class="hljs-title function_">padStart</span>(<span class="hljs-number">6</span>, <span class="hljs-number">0</span>); | |
| <span class="hljs-comment">// Draw the box</span> | |
| <span class="hljs-keyword">const</span> boxElement = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">"div"</span>); | |
| boxElement.<span class="hljs-property">className</span> = <span class="hljs-string">"bounding-box"</span>; | |
| <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">assign</span>(boxElement.<span class="hljs-property">style</span>, { | |
| <span class="hljs-attr">borderColor</span>: color, | |
| <span class="hljs-attr">left</span>: <span class="hljs-number">100</span> * xmin + <span class="hljs-string">"%"</span>, | |
| <span class="hljs-attr">top</span>: <span class="hljs-number">100</span> * ymin + <span class="hljs-string">"%"</span>, | |
| <span class="hljs-attr">width</span>: <span class="hljs-number">100</span> * (xmax - xmin) + <span class="hljs-string">"%"</span>, | |
| <span class="hljs-attr">height</span>: <span class="hljs-number">100</span> * (ymax - ymin) + <span class="hljs-string">"%"</span>, | |
| }); | |
| <span class="hljs-comment">// Draw the label</span> | |
| <span class="hljs-keyword">const</span> labelElement = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">"span"</span>); | |
| labelElement.<span class="hljs-property">textContent</span> = label; | |
| labelElement.<span class="hljs-property">className</span> = <span class="hljs-string">"bounding-box-label"</span>; | |
| labelElement.<span class="hljs-property">style</span>.<span class="hljs-property">backgroundColor</span> = color; | |
| boxElement.<span class="hljs-title function_">appendChild</span>(labelElement); | |
| imageContainer.<span class="hljs-title function_">appendChild</span>(boxElement); | |
| }<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1otf5ry">The bounding box and label span also need some styling, so add the following to the <code>style.css</code> file:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-selector-class">.bounding-box</span> { | |
| <span class="hljs-attribute">position</span>: absolute; | |
| <span class="hljs-attribute">box-sizing</span>: border-box; | |
| <span class="hljs-attribute">border-width</span>: <span class="hljs-number">2px</span>; | |
| <span class="hljs-attribute">border-style</span>: solid; | |
| } | |
| <span class="hljs-selector-class">.bounding-box-label</span> { | |
| <span class="hljs-attribute">color</span>: white; | |
| <span class="hljs-attribute">position</span>: absolute; | |
| <span class="hljs-attribute">font-size</span>: <span class="hljs-number">12px</span>; | |
| <span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">16px</span>; | |
| <span class="hljs-attribute">margin-left</span>: -<span class="hljs-number">2px</span>; | |
| <span class="hljs-attribute">padding</span>: <span class="hljs-number">1px</span>; | |
| }<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-4x54i7"><strong>And that’s it!</strong></p> <p data-svelte-h="svelte-19bn35c">You’ve now built your own fully-functional AI application that detects objects in images, which runs completely in your browser: no external server, APIs, or build tools. Pretty cool! 🥳</p> <p data-svelte-h="svelte-1yhdijg"><img src="https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/js-detection-inference-elephant.png" alt="Demo"></p> <p data-svelte-h="svelte-9xei6b">The app is live at the following URL: <a href="https://huggingface.co/spaces/Scrimba/vanilla-js-object-detector" rel="nofollow">https://huggingface.co/spaces/Scrimba/vanilla-js-object-detector</a></p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/transformers.js/blob/main/packages/transformers/docs/source/tutorials/vanilla-js.md" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg> <span data-svelte-h="svelte-zjs2n5"><span class="underline">Update</span> on GitHub</span></a> <p></p> | |
| <script> | |
| { | |
| __sveltekit_rvrl7f = { | |
| assets: "/docs/transformers.js/pr_1649/en", | |
| base: "/docs/transformers.js/pr_1649/en", | |
| env: {} | |
| }; | |
| const element = document.currentScript.parentElement; | |
| const data = [null,null]; | |
| Promise.all([ | |
| import("/docs/transformers.js/pr_1649/en/_app/immutable/entry/start.5f753a22.js"), | |
| import("/docs/transformers.js/pr_1649/en/_app/immutable/entry/app.db3dfcb7.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 40], | |
| data, | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 54.9 kB
- Xet hash:
- 464ead3adc19e5f930a0e79ceb9c4e25433bd90b57f97490c6ca78f484eb9ed1
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.