Alan Ren
commited on
Commit
·
057f6a7
1
Parent(s):
8c200b4
chore: Remove unused code and update object detection logic
Browse files
index.js
DELETED
@@ -1,79 +0,0 @@
|
|
1 |
-
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/[email protected]';
|
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 |
-
// Reference the elements that we will need
|
7 |
-
const status = document.getElementById('status');
|
8 |
-
const fileUpload = document.getElementById('upload');
|
9 |
-
const imageContainer = document.getElementById('container');
|
10 |
-
const example = document.getElementById('example');
|
11 |
-
|
12 |
-
const EXAMPLE_URL = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/city-streets.jpg';
|
13 |
-
|
14 |
-
// Create a new object detection pipeline
|
15 |
-
status.textContent = 'Loading model...';
|
16 |
-
const detector = await pipeline('object-detection', 'Xenova/detr-resnet-50');
|
17 |
-
status.textContent = 'Ready';
|
18 |
-
|
19 |
-
example.addEventListener('click', (e) => {
|
20 |
-
e.preventDefault();
|
21 |
-
detect(EXAMPLE_URL);
|
22 |
-
});
|
23 |
-
|
24 |
-
fileUpload.addEventListener('change', function (e) {
|
25 |
-
const file = e.target.files[0];
|
26 |
-
if (!file) {
|
27 |
-
return;
|
28 |
-
}
|
29 |
-
|
30 |
-
const reader = new FileReader();
|
31 |
-
|
32 |
-
// Set up a callback when the file is loaded
|
33 |
-
reader.onload = e2 => detect(e2.target.result);
|
34 |
-
|
35 |
-
reader.readAsDataURL(file);
|
36 |
-
});
|
37 |
-
|
38 |
-
|
39 |
-
// Detect objects in the image
|
40 |
-
async function detect(img) {
|
41 |
-
imageContainer.innerHTML = '';
|
42 |
-
imageContainer.style.backgroundImage = `url(${img})`;
|
43 |
-
|
44 |
-
status.textContent = 'Analysing...';
|
45 |
-
const output = await detector(img, {
|
46 |
-
threshold: 0.5,
|
47 |
-
percentage: true,
|
48 |
-
});
|
49 |
-
status.textContent = '';
|
50 |
-
output.forEach(renderBox);
|
51 |
-
}
|
52 |
-
|
53 |
-
// Render a bounding box and label on the image
|
54 |
-
function renderBox({ box, label }) {
|
55 |
-
const { xmax, xmin, ymax, ymin } = box;
|
56 |
-
|
57 |
-
// Generate a random color for the box
|
58 |
-
const color = '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, 0);
|
59 |
-
|
60 |
-
// Draw the box
|
61 |
-
const boxElement = document.createElement('div');
|
62 |
-
boxElement.className = 'bounding-box';
|
63 |
-
Object.assign(boxElement.style, {
|
64 |
-
borderColor: color,
|
65 |
-
left: 100 * xmin + '%',
|
66 |
-
top: 100 * ymin + '%',
|
67 |
-
width: 100 * (xmax - xmin) + '%',
|
68 |
-
height: 100 * (ymax - ymin) + '%',
|
69 |
-
})
|
70 |
-
|
71 |
-
// Draw label
|
72 |
-
const labelElement = document.createElement('span');
|
73 |
-
labelElement.textContent = label;
|
74 |
-
labelElement.className = 'bounding-box-label';
|
75 |
-
labelElement.style.backgroundColor = color;
|
76 |
-
|
77 |
-
boxElement.appendChild(labelElement);
|
78 |
-
imageContainer.appendChild(boxElement);
|
79 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p5.min.js
DELETED
The diff for this file is too large to render.
See raw diff
|
|
sketch.js
CHANGED
@@ -12,20 +12,22 @@ let statusP;
|
|
12 |
|
13 |
// Preload function to load the default image and convert it to a base64 data URL
|
14 |
function preload() {
|
15 |
-
defaultImg1 =
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
});
|
|
|
22 |
|
23 |
-
|
24 |
-
|
|
|
25 |
let offscreenGraphics = createGraphics(img.width, img.height);
|
26 |
offscreenGraphics.image(img, 0, 0);
|
27 |
-
|
28 |
-
|
29 |
});
|
30 |
}
|
31 |
|
@@ -57,27 +59,16 @@ function setup() {
|
|
57 |
|
58 |
// Create a file input for image upload
|
59 |
createFileInput(imageUploaded).attribute('accept', 'image/*');
|
60 |
-
createButton('Example 1').mousePressed(
|
61 |
-
createButton('Example 2').mousePressed(
|
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 |
-
|
|
|
75 |
if (imgElement) {
|
76 |
imgElement.remove();
|
77 |
}
|
78 |
-
|
79 |
-
imgElement = createImg(defaultImg2DataURL, '').hide();
|
80 |
-
// Immediately perform detection on the default image
|
81 |
detect(imgElement);
|
82 |
}
|
83 |
|
@@ -87,9 +78,7 @@ function imageUploaded(file) {
|
|
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.');
|
@@ -104,44 +93,34 @@ async function detect(image) {
|
|
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;
|
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;
|
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);
|
|
|
12 |
|
13 |
// Preload function to load the default image and convert it to a base64 data URL
|
14 |
function preload() {
|
15 |
+
defaultImg1 = loadAndConvertImage('https://cors-anywhere-ajr.up.railway.app/https://hdwallpaperim.com/wp-content/uploads/2017/08/25/452511-street-street_view-cityscape-city.jpg', (dataURL) => {
|
16 |
+
defaultImg1DataURL = dataURL;
|
17 |
+
});
|
18 |
+
|
19 |
+
defaultImg2 = loadAndConvertImage('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', (dataURL) => {
|
20 |
+
defaultImg2DataURL = dataURL;
|
21 |
});
|
22 |
+
}
|
23 |
|
24 |
+
// Function to load an image and convert it to a base64 data URL
|
25 |
+
function loadAndConvertImage(url, callback) {
|
26 |
+
return loadImage(url, (img) => {
|
27 |
let offscreenGraphics = createGraphics(img.width, img.height);
|
28 |
offscreenGraphics.image(img, 0, 0);
|
29 |
+
let dataURL = offscreenGraphics.elt.toDataURL();
|
30 |
+
callback(dataURL);
|
31 |
});
|
32 |
}
|
33 |
|
|
|
59 |
|
60 |
// Create a file input for image upload
|
61 |
createFileInput(imageUploaded).attribute('accept', 'image/*');
|
62 |
+
createButton('Example 1').mousePressed(() => loadExampleImage(defaultImg1DataURL));
|
63 |
+
createButton('Example 2').mousePressed(() => loadExampleImage(defaultImg2DataURL));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
}
|
65 |
|
66 |
+
// Function to load an example image
|
67 |
+
function loadExampleImage(dataURL) {
|
68 |
if (imgElement) {
|
69 |
imgElement.remove();
|
70 |
}
|
71 |
+
imgElement = createImg(dataURL, '').hide();
|
|
|
|
|
72 |
detect(imgElement);
|
73 |
}
|
74 |
|
|
|
78 |
if (imgElement) {
|
79 |
imgElement.remove(); // Remove the previous image if exists
|
80 |
}
|
|
|
81 |
imgElement = createImg(file.data, '').hide();
|
|
|
82 |
detect(imgElement);
|
83 |
} else {
|
84 |
statusP.html('Please upload an image file.');
|
|
|
93 |
percentage: true,
|
94 |
});
|
95 |
|
|
|
96 |
displayImageAndBoxes(image, results);
|
97 |
statusP.html('Image Processed');
|
98 |
}
|
99 |
|
100 |
// Function to display the image and bounding boxes on the canvas
|
101 |
function displayImageAndBoxes(img, results) {
|
|
|
102 |
let scaleX = windowWidth / img.width;
|
103 |
+
let scaleY = scaleX;
|
104 |
|
|
|
105 |
let scaledWidth = img.width * scaleX;
|
106 |
let scaledHeight = img.height * scaleY;
|
107 |
|
|
|
108 |
resizeCanvas(windowWidth, scaledHeight + 200);
|
|
|
|
|
109 |
image(img, 0, 100, scaledWidth, scaledHeight);
|
110 |
|
|
|
111 |
for (const result of results) {
|
112 |
const { box, label } = result;
|
113 |
const { xmax, xmin, ymax, ymin } = box;
|
114 |
|
|
|
115 |
let rectX = xmin * scaledWidth;
|
116 |
+
let rectY = ymin * scaledHeight + 100;
|
117 |
let rectWidth = (xmax - xmin) * scaledWidth;
|
118 |
let rectHeight = (ymax - ymin) * scaledHeight;
|
119 |
|
|
|
120 |
stroke(255, 0, 0);
|
121 |
noFill();
|
122 |
rect(rectX, rectY, rectWidth, rectHeight);
|
123 |
|
|
|
124 |
fill(255);
|
125 |
strokeWeight(1);
|
126 |
textSize(16);
|