You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, themeColor = "#FFD700") {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0);
// Helper to draw messages for users on the canvas
const drawMessage = (msg, isError = false) => {
let fontSize = Math.max(16, Math.floor(canvas.width / 35));
ctx.fillStyle = isError ? 'rgba(255, 0, 0, 0.7)' : 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, canvas.width, fontSize * 2 + 20);
ctx.fillStyle = 'white';
ctx.font = `${fontSize}px Arial`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(msg, canvas.width / 2, fontSize + 10);
};
// 1. Dynamically load the 'face-api.js' library if it isn't already loaded
if (!window.faceapi) {
try {
await new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/@vladmandic/face-api@1.7.12/dist/face-api.min.js';
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
} catch (err) {
drawMessage("Ошибка загрузки модуля анализатора (Script load failed)", true);
return canvas; // Return early with the error drawn
}
}
try {
// Draw a temporary analyzing state
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
ctx.fillRect(0, canvas.height - 50, canvas.width, 50);
ctx.fillStyle = 'white';
let loadingFontSize = Math.max(14, Math.floor(canvas.width / 40));
ctx.font = `${loadingFontSize}px Arial`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText("Нейросеть анализирует красоту... (Analyzing beauty...)", canvas.width / 2, canvas.height - 25);
// 2. Load the lightweight TinyFaceDetector models
const MODEL_URL = 'https://cdn.jsdelivr.net/npm/@vladmandic/face-api@1.7.12/model/';
await faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL);
// 3. Detect all faces in the canvas image
const detections = await faceapi.detectAllFaces(canvas, new faceapi.TinyFaceDetectorOptions());
// Restore image to clear the analyzing state text
ctx.drawImage(originalImg, 0, 0);
// 4. Handle cases with no faces detected
if (!detections || detections.length === 0) {
drawMessage("Лица не найдены (No faces detected)");
return canvas;
}
// 5. Calculate a pseudo-random "beauty score" based consistently on their coordinate hash
const faces = detections.map(det => {
const box = det.box;
// Generate deterministic result so the same image yields the same exact "verdict"
const seed = Math.floor(box.x + box.y + box.width + box.height);
const randomVal = Math.abs(Math.sin(seed * 12.9898));
// Score bounded between 70 and 100
const score = Math.floor(randomVal * 31) + 70;
return { box, score };
});
// 6. Find who is the most beautiful
const highestScore = Math.max(...faces.map(f => f.score));
// 7. Draw bounding boxes and scores mimicking an AI beauty scanner
faces.forEach((face) => {
const { box, score } = face;
// A winner only exists if there are multiple faces competing
const isWinner = (score === highestScore) && (faces.length > 1);
const color = isWinner ? themeColor : '#FF4500'; // Theme color (Gold) for winner, Orange for others
ctx.strokeStyle = color;
ctx.lineWidth = Math.max(3, canvas.width / 200);
ctx.strokeRect(box.x, box.y, box.width, box.height);
const text = isWinner ? `👑 Победитель: ${score}/100` : `Рейтинг: ${score}/100`;
const fontSize = Math.max(14, Math.floor(canvas.width / 35));
ctx.font = `bold ${fontSize}px sans-serif`;
const textWidth = ctx.measureText(text).width;
const textHeight = fontSize;
const labelY = Math.max(textHeight + 10, box.y);
// Label background
ctx.fillStyle = color;
ctx.fillRect(box.x - ctx.lineWidth / 2, labelY - textHeight - 10, textWidth + 20, textHeight + 14);
// Label text
ctx.fillStyle = isWinner ? '#000000' : '#FFFFFF';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(text, box.x + 10, labelY - textHeight - 3);
});
} catch (e) {
console.error(e);
ctx.drawImage(originalImg, 0, 0); // Restore to clear visual artifacts
drawMessage("Ошибка анализа алгоритмом (Analysis error)", true);
}
// 8. Output generated visual comparison canvas
return canvas;
}
Apply Changes