Alan Ren
commited on
Commit
·
8c200b4
1
Parent(s):
4b9eaec
Update HTML and CSS files for Transformers.js demo page
Browse files- index.html +11 -22
- modules/ort-training-wasm-simd.wasm +3 -0
- modules/ort-wasm-simd-threaded.jsep.wasm +3 -0
- modules/ort-wasm-simd-threaded.wasm +3 -0
- modules/ort-wasm-simd.jsep.wasm +3 -0
- modules/ort-wasm-simd.wasm +3 -0
- modules/ort-wasm-threaded.wasm +3 -0
- modules/ort-wasm.wasm +3 -0
- modules/transformerLoader.js +7 -0
- modules/transformers.cjs +0 -0
- modules/transformers.cjs.map +0 -0
- modules/transformers.js +0 -0
- modules/transformers.js.map +0 -0
- modules/transformers.min.cjs +0 -0
- modules/transformers.min.cjs.map +0 -0
- modules/transformers.min.js +0 -0
- modules/transformers.min.js.map +0 -0
- p5.min.js +0 -0
- sketch.js +155 -0
- style.css +38 -56
index.html
CHANGED
@@ -1,29 +1,18 @@
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="en">
|
3 |
-
|
4 |
-
<head>
|
5 |
<meta charset="UTF-8" />
|
6 |
<link rel="stylesheet" href="style.css" />
|
7 |
-
|
8 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
9 |
-
<title>Transformers.js - Object Detection</title>
|
10 |
-
|
11 |
-
|
12 |
-
<body>
|
13 |
-
<h1>Object Detection w/ 🤗 Transformers.js</h1>
|
14 |
-
<label id="container" for="upload">
|
15 |
-
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
16 |
-
<path fill="#000"
|
17 |
-
d="M3.5 24.3a3 3 0 0 1-1.9-.8c-.5-.5-.8-1.2-.8-1.9V2.9c0-.7.3-1.3.8-1.9.6-.5 1.2-.7 2-.7h18.6c.7 0 1.3.2 1.9.7.5.6.7 1.2.7 2v18.6c0 .7-.2 1.4-.7 1.9a3 3 0 0 1-2 .8H3.6Zm0-2.7h18.7V2.9H3.5v18.7Zm2.7-2.7h13.3c.3 0 .5 0 .6-.3v-.7l-3.7-5a.6.6 0 0 0-.6-.2c-.2 0-.4 0-.5.3l-3.5 4.6-2.4-3.3a.6.6 0 0 0-.6-.3c-.2 0-.4.1-.5.3l-2.7 3.6c-.1.2-.2.4 0 .7.1.2.3.3.6.3Z">
|
18 |
-
</path>
|
19 |
-
</svg>
|
20 |
-
Click to upload image
|
21 |
-
<label id="example">(or try example)</label>
|
22 |
-
</label>
|
23 |
-
<label id="status">Loading model...</label>
|
24 |
-
<input id="upload" type="file" accept="image/*" />
|
25 |
|
26 |
-
|
27 |
-
|
|
|
28 |
|
29 |
-
|
|
|
|
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="en">
|
3 |
+
<head>
|
|
|
4 |
<meta charset="UTF-8" />
|
5 |
<link rel="stylesheet" href="style.css" />
|
|
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
+
<title>Transformers.js - Object Detection demo</title>
|
8 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.2/p5.min.js"></script>
|
9 |
+
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
+
<body>
|
12 |
+
<main class="container"></main>
|
13 |
+
<script src="./modules/transformerLoader.js" type="module"></script>
|
14 |
|
15 |
+
|
16 |
+
<script src="sketch.js"></script>
|
17 |
+
</body>
|
18 |
+
</html>
|
modules/ort-training-wasm-simd.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f8805ba34df33de24f893e5c5b2f177c98bfb28b201261478611ec0c6df6514f
|
3 |
+
size 11271689
|
modules/ort-wasm-simd-threaded.jsep.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0b47636210089367dc219ea498059e3f821527f7e9daca4a8f553e3ec54b0bdf
|
3 |
+
size 19532837
|
modules/ort-wasm-simd-threaded.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c81546f91f8ba7145001262480e3f8e764ffe49615940e676c276b764197e1dd
|
3 |
+
size 10647985
|
modules/ort-wasm-simd.jsep.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d4052bde30200dcb268684067ccb748adb62c64a219b270021f26f12c24dcefe
|
3 |
+
size 17426424
|
modules/ort-wasm-simd.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:6783fcd6647ce1b426a527c31412a9c40894552faa609e9c931b3239a3438071
|
3 |
+
size 10551547
|
modules/ort-wasm-threaded.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:985939271fdd3176dd0ef78c567e0cfa7405d33f3ddc4fed7da9c65b54830f9a
|
3 |
+
size 9818517
|
modules/ort-wasm.wasm
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:969afd00c79afead28a90b6acd01bd64abe4b5ac8bc9650c3dee3aefc6e0cea6
|
3 |
+
size 9726745
|
modules/transformerLoader.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { pipeline, env } from './transformers.js';
|
2 |
+
|
3 |
+
// Since we will download the model from the Hugging Face Hub, we can skip the local model check
|
4 |
+
env.allowLocalModels = false;
|
5 |
+
|
6 |
+
// Export the pipeline funco it can be used in other files
|
7 |
+
window.transformersPipeline = pipeline;
|
modules/transformers.cjs
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.cjs.map
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.js
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.js.map
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.min.cjs
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.min.cjs.map
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.min.js
ADDED
The diff for this file is too large to render.
See raw diff
|
|
modules/transformers.min.js.map
ADDED
The diff for this file is too large to render.
See raw diff
|
|
p5.min.js
ADDED
The diff for this file is too large to render.
See raw diff
|
|
sketch.js
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Alan Ren @NYU ITP
|
2 |
+
// Spring 2024
|
3 |
+
|
4 |
+
// Global variables for the detector, image elements, and status paragraph
|
5 |
+
let detector;
|
6 |
+
let imgElement,
|
7 |
+
defaultImg1,
|
8 |
+
defaultImg1DataURL,
|
9 |
+
defaultImg2,
|
10 |
+
defaultImg2DataURL;
|
11 |
+
let statusP;
|
12 |
+
|
13 |
+
// Preload function to load the default image and convert it to a base64 data URL
|
14 |
+
function preload() {
|
15 |
+
defaultImg1 = loadImage('https://cors-anywhere-ajr.up.railway.app/https://hdwallpaperim.com/wp-content/uploads/2017/08/25/452511-street-street_view-cityscape-city.jpg', (img) => {
|
16 |
+
// Create an offscreen graphics object to draw the image for conversion
|
17 |
+
let offscreenGraphics = createGraphics(img.width, img.height);
|
18 |
+
offscreenGraphics.image(img, 0, 0);
|
19 |
+
// Convert the drawn image on canvas to Data URL (base64)
|
20 |
+
defaultImg1DataURL = offscreenGraphics.elt.toDataURL();
|
21 |
+
});
|
22 |
+
|
23 |
+
defaultImg2 = loadImage('https://cors-anywhere-ajr.up.railway.app/https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fdirectoffice.com%2Fwp-content%2Fuploads%2F2024%2F06%2FOffice-Storage-Cabinets-2048x1366.jpg&f=1&nofb=1&ipt=f6b591aded06e6451a47bac25c3b6fe04aa285fb7796c7bc35b881e063a07a5f&ipo=images', (img) => {
|
24 |
+
// Create an offscreen graphics object to draw the image for conversion
|
25 |
+
let offscreenGraphics = createGraphics(img.width, img.height);
|
26 |
+
offscreenGraphics.image(img, 0, 0);
|
27 |
+
// Convert the drawn image on canvas to Data URL (base64)
|
28 |
+
defaultImg2DataURL = offscreenGraphics.elt.toDataURL();
|
29 |
+
});
|
30 |
+
}
|
31 |
+
|
32 |
+
// Setup function initializes the p5 sketch
|
33 |
+
function setup() {
|
34 |
+
// Create a paragraph element to show status messages
|
35 |
+
statusP = createP('Loading model...').style('color', 'blue');
|
36 |
+
|
37 |
+
// Check if the transformersPipeline is loaded and available
|
38 |
+
if (typeof window.transformersPipeline === 'undefined') {
|
39 |
+
console.error('Transformers pipeline not available!');
|
40 |
+
statusP.html('Pipeline loading failed.');
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
|
44 |
+
// Initialize the object detection model using the transformersPipeline
|
45 |
+
window
|
46 |
+
.transformersPipeline('object-detection', 'Xenova/yolos-tiny', {
|
47 |
+
device: 'webgpu',
|
48 |
+
})
|
49 |
+
.then((d) => {
|
50 |
+
detector = d;
|
51 |
+
statusP.html('Model ready. Upload an image.');
|
52 |
+
})
|
53 |
+
.catch((error) => {
|
54 |
+
console.error('Error loading the model: ', error);
|
55 |
+
statusP.html('Model loading failed.');
|
56 |
+
});
|
57 |
+
|
58 |
+
// Create a file input for image upload
|
59 |
+
createFileInput(imageUploaded).attribute('accept', 'image/*');
|
60 |
+
createButton('Example 1').mousePressed(loadImg1);
|
61 |
+
createButton('Example 2').mousePressed(loadImg2);
|
62 |
+
}
|
63 |
+
|
64 |
+
function loadImg1() {
|
65 |
+
if (imgElement) {
|
66 |
+
imgElement.remove();
|
67 |
+
}
|
68 |
+
// Initialize the imgElement with the preloaded default image #2
|
69 |
+
imgElement = createImg(defaultImg1DataURL, '').hide();
|
70 |
+
// Immediately perform detection on the default image
|
71 |
+
detect(imgElement);
|
72 |
+
}
|
73 |
+
|
74 |
+
function loadImg2() {
|
75 |
+
if (imgElement) {
|
76 |
+
imgElement.remove();
|
77 |
+
}
|
78 |
+
// Initialize the imgElement with the preloaded default image #2
|
79 |
+
imgElement = createImg(defaultImg2DataURL, '').hide();
|
80 |
+
// Immediately perform detection on the default image
|
81 |
+
detect(imgElement);
|
82 |
+
}
|
83 |
+
|
84 |
+
// Function to handle uploaded images
|
85 |
+
function imageUploaded(file) {
|
86 |
+
if (file.type === 'image') {
|
87 |
+
if (imgElement) {
|
88 |
+
imgElement.remove(); // Remove the previous image if exists
|
89 |
+
}
|
90 |
+
// Create an image element with the uploaded file
|
91 |
+
imgElement = createImg(file.data, '').hide();
|
92 |
+
// Detect objects in the uploaded image
|
93 |
+
detect(imgElement);
|
94 |
+
} else {
|
95 |
+
statusP.html('Please upload an image file.');
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
// Function to perform object detection
|
100 |
+
async function detect(image) {
|
101 |
+
statusP.html('Analysing...');
|
102 |
+
const results = await detector(image.elt.src, {
|
103 |
+
threshold: 0.5,
|
104 |
+
percentage: true,
|
105 |
+
});
|
106 |
+
|
107 |
+
// Display the image and bounding boxes once analysis is complete
|
108 |
+
displayImageAndBoxes(image, results);
|
109 |
+
statusP.html('Image Processed');
|
110 |
+
}
|
111 |
+
|
112 |
+
// Function to display the image and bounding boxes on the canvas
|
113 |
+
function displayImageAndBoxes(img, results) {
|
114 |
+
// Calculate scale to fit the image to the screen width while maintaining aspect ratio
|
115 |
+
let scaleX = windowWidth / img.width;
|
116 |
+
let scaleY = scaleX; // Maintain aspect ratio
|
117 |
+
|
118 |
+
// Adjust the canvas to fit the scaled image
|
119 |
+
let scaledWidth = img.width * scaleX;
|
120 |
+
let scaledHeight = img.height * scaleY;
|
121 |
+
|
122 |
+
// Resize the canvas to fit the scaled image and provide space for status
|
123 |
+
resizeCanvas(windowWidth, scaledHeight + 200);
|
124 |
+
|
125 |
+
// Draw the scaled image on the canvas
|
126 |
+
image(img, 0, 100, scaledWidth, scaledHeight);
|
127 |
+
|
128 |
+
// Iterate over each result to draw bounding boxes and labels
|
129 |
+
for (const result of results) {
|
130 |
+
const { box, label } = result;
|
131 |
+
const { xmax, xmin, ymax, ymin } = box;
|
132 |
+
|
133 |
+
// Calculate coordinates and dimensions for scaled bounding boxes
|
134 |
+
let rectX = xmin * scaledWidth;
|
135 |
+
let rectY = ymin * scaledHeight + 100; // Offset by 100 pixels from top
|
136 |
+
let rectWidth = (xmax - xmin) * scaledWidth;
|
137 |
+
let rectHeight = (ymax - ymin) * scaledHeight;
|
138 |
+
|
139 |
+
// Draw bounding box
|
140 |
+
stroke(255, 0, 0);
|
141 |
+
noFill();
|
142 |
+
rect(rectX, rectY, rectWidth, rectHeight);
|
143 |
+
|
144 |
+
// Draw label above the bounding box
|
145 |
+
fill(255);
|
146 |
+
strokeWeight(1);
|
147 |
+
textSize(16);
|
148 |
+
text(label, rectX, rectY - 10);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
// The draw function is left empty because updates only occur during detection
|
153 |
+
function draw() {
|
154 |
+
// Leave this function empty if updates only occur during detection
|
155 |
+
}
|
style.css
CHANGED
@@ -1,76 +1,58 @@
|
|
1 |
-
* {
|
2 |
-
box-sizing: border-box;
|
3 |
-
padding: 0;
|
4 |
-
margin: 0;
|
5 |
-
font-family: sans-serif;
|
6 |
-
}
|
7 |
-
|
8 |
html,
|
9 |
body {
|
10 |
-
|
|
|
11 |
}
|
12 |
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
15 |
}
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
23 |
}
|
24 |
|
25 |
-
#
|
26 |
-
|
27 |
-
gap: 0.4rem;
|
28 |
-
|
29 |
-
width: 640px;
|
30 |
-
height: 640px;
|
31 |
-
max-width: 100%;
|
32 |
-
max-height: 100%;
|
33 |
-
|
34 |
-
border: 2px dashed #D1D5DB;
|
35 |
-
border-radius: 0.75rem;
|
36 |
-
overflow: hidden;
|
37 |
-
cursor: pointer;
|
38 |
-
margin: 1rem;
|
39 |
-
|
40 |
-
background-size: 100% 100%;
|
41 |
-
background-position: center;
|
42 |
-
background-repeat: no-repeat;
|
43 |
-
font-size: 18px;
|
44 |
-
}
|
45 |
-
|
46 |
-
#upload {
|
47 |
-
display: none;
|
48 |
}
|
49 |
|
50 |
-
|
51 |
-
|
52 |
}
|
53 |
|
54 |
-
#
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
}
|
59 |
|
60 |
-
#
|
61 |
-
|
62 |
}
|
63 |
|
64 |
.bounding-box {
|
65 |
-
|
66 |
-
|
67 |
-
|
|
|
68 |
}
|
69 |
|
70 |
.bounding-box-label {
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
html,
|
2 |
body {
|
3 |
+
font-family: Arial, Helvetica, sans-serif;
|
4 |
+
background-color: #137890;
|
5 |
}
|
6 |
|
7 |
+
.container {
|
8 |
+
margin: 40px auto;
|
9 |
+
width: max(50vw, 400px);
|
10 |
+
display: flex;
|
11 |
+
flex-direction: column;
|
12 |
+
align-items: center;
|
13 |
}
|
14 |
|
15 |
+
.custom-file-upload {
|
16 |
+
display: flex;
|
17 |
+
align-items: center;
|
18 |
+
cursor: pointer;
|
19 |
+
gap: 10px;
|
20 |
+
border: 2px solid black;
|
21 |
+
padding: 8px 16px;
|
22 |
+
cursor: pointer;
|
23 |
+
border-radius: 6px;
|
24 |
}
|
25 |
|
26 |
+
#file-upload {
|
27 |
+
display: none;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
}
|
29 |
|
30 |
+
.upload-icon {
|
31 |
+
width: 30px;
|
32 |
}
|
33 |
|
34 |
+
#image-container {
|
35 |
+
width: 100%;
|
36 |
+
margin-top: 20px;
|
37 |
+
position: relative;
|
38 |
}
|
39 |
|
40 |
+
#image-container > img {
|
41 |
+
width: 100%;
|
42 |
}
|
43 |
|
44 |
.bounding-box {
|
45 |
+
position: absolute;
|
46 |
+
box-sizing: border-box;
|
47 |
+
border-width: 2px;
|
48 |
+
border-style: solid;
|
49 |
}
|
50 |
|
51 |
.bounding-box-label {
|
52 |
+
color: white;
|
53 |
+
position: absolute;
|
54 |
+
font-size: 12px;
|
55 |
+
margin-top: -16px;
|
56 |
+
margin-left: -2px;
|
57 |
+
padding: 1px;
|
58 |
+
}
|