// Alan Ren @NYU ITP // Spring 2024 // Global variables for the detector, image elements, and status paragraph let detector; let imgElement, defaultImg1, defaultImg1DataURL, defaultImg2, defaultImg2DataURL; let statusP; // Preload function to load the default image and convert it to a base64 data URL function preload() { 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) => { defaultImg1DataURL = dataURL; }); 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) => { defaultImg2DataURL = dataURL; }); } // Function to load an image and convert it to a base64 data URL function loadAndConvertImage(url, callback) { return loadImage(url, (img) => { let offscreenGraphics = createGraphics(img.width, img.height); offscreenGraphics.image(img, 0, 0); let dataURL = offscreenGraphics.elt.toDataURL(); callback(dataURL); }); } // Setup function initializes the p5 sketch function setup() { // Create a paragraph element to show status messages statusP = createP('Loading model...').style('color', 'blue'); // Check if the transformersPipeline is loaded and available if (typeof window.transformersPipeline === 'undefined') { console.error('Transformers pipeline not available!'); statusP.html('Pipeline loading failed.'); return; } // Initialize the object detection model using the transformersPipeline window .transformersPipeline('object-detection', 'Xenova/yolos-tiny', { device: 'webgpu', }) .then((d) => { detector = d; statusP.html('Model ready. Upload an image.'); }) .catch((error) => { console.error('Error loading the model: ', error); statusP.html('Model loading failed.'); }); // Create a file input for image upload createFileInput(imageUploaded).attribute('accept', 'image/*'); createButton('Example 1').mousePressed(() => loadExampleImage(defaultImg1DataURL)); createButton('Example 2').mousePressed(() => loadExampleImage(defaultImg2DataURL)); } // Function to load an example image function loadExampleImage(dataURL) { if (imgElement) { imgElement.remove(); } imgElement = createImg(dataURL, '').hide(); detect(imgElement); } // Function to handle uploaded images function imageUploaded(file) { if (file.type === 'image') { if (imgElement) { imgElement.remove(); // Remove the previous image if exists } imgElement = createImg(file.data, '').hide(); detect(imgElement); } else { statusP.html('Please upload an image file.'); } } // Function to perform object detection async function detect(image) { statusP.html('Analysing...'); const results = await detector(image.elt.src, { threshold: 0.5, percentage: true, }); displayImageAndBoxes(image, results); statusP.html('Image Processed'); } // Function to display the image and bounding boxes on the canvas function displayImageAndBoxes(img, results) { let scaleX = windowWidth / img.width; let scaleY = scaleX; let scaledWidth = img.width * scaleX; let scaledHeight = img.height * scaleY; resizeCanvas(windowWidth, scaledHeight + 200); image(img, 0, 100, scaledWidth, scaledHeight); for (const result of results) { const { box, label } = result; const { xmax, xmin, ymax, ymin } = box; let rectX = xmin * scaledWidth; let rectY = ymin * scaledHeight + 100; let rectWidth = (xmax - xmin) * scaledWidth; let rectHeight = (ymax - ymin) * scaledHeight; stroke(255, 0, 0); noFill(); rect(rectX, rectY, rectWidth, rectHeight); fill(255); strokeWeight(1); textSize(16); text(label, rectX, rectY - 10); } } // The draw function is left empty because updates only occur during detection function draw() { // Leave this function empty if updates only occur during detection }