Alan Ren commited on
Commit
8c200b4
·
1 Parent(s): 4b9eaec

Update HTML and CSS files for Transformers.js demo page

Browse files
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
- </head>
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
- <script src="index.js" type="module"></script>
27
- </body>
 
28
 
29
- </html>
 
 
 
 
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
- height: 100%;
 
11
  }
12
 
13
- body {
14
- padding: 32px;
 
 
 
 
15
  }
16
 
17
- body,
18
- #container {
19
- display: flex;
20
- flex-direction: column;
21
- justify-content: center;
22
- align-items: center;
 
 
 
23
  }
24
 
25
- #container {
26
- position: relative;
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
- svg {
51
- pointer-events: none;
52
  }
53
 
54
- #example {
55
- font-size: 14px;
56
- text-decoration: underline;
57
- cursor: pointer;
58
  }
59
 
60
- #example:hover {
61
- color: #2563EB;
62
  }
63
 
64
  .bounding-box {
65
- position: absolute;
66
- box-sizing: border-box;
67
- border: solid 2px;
 
68
  }
69
 
70
  .bounding-box-label {
71
- color: white;
72
- position: absolute;
73
- font-size: 12px;
74
- margin: -16px 0 0 -2px;
75
- padding: 1px;
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
+ }