You can edit the below JavaScript code to customize the image tool.
/**
* Identifies and counts petal-like shapes in an image of a flower.
* This function works by identifying the main subject (the flower) based on a brightness threshold,
* finding its center, and then performing several circular scans at different radii from that center.
* On each scan, it counts the number of times it transitions from a darker background to a brighter
* area (assumed to be a petal). The median of these counts is returned as the final estimate.
*
* @param {Image} originalImg The original input Image object.
* @param {number} brightnessThreshold=128 A value from 0 to 255. Pixels brighter than this value are considered part of the flower. Adjust this based on image lighting.
* @param {number} scanDetail=10 The number of concentric circles to scan for petals. A higher number is more accurate but slower.
* @returns {HTMLCanvasElement} A new canvas element displaying the original image with the estimated petal count overlaid.
*/
async function processImage(originalImg, brightnessThreshold = 128, scanDetail = 10) {
// 1. Setup Canvas and draw the image
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
ctx.drawImage(originalImg, 0, 0);
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// Handle potential cross-origin security errors
console.error("Could not get image data. Ensure the image is from the same origin or has CORS headers.", e);
ctx.fillStyle = 'rgba(255, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height - 50, canvas.width, 50);
ctx.font = 'bold 16px Arial';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Error: Cannot process cross-origin image.', canvas.width / 2, canvas.height - 25);
return canvas;
}
const data = imageData.data;
// 2. Analyze image to find the flower's center and bounds
// We calculate the center of mass of all pixels above the brightness threshold.
let sumX = 0, sumY = 0, brightPixelCount = 0;
let minX = canvas.width, minY = canvas.height, maxX = 0, maxY = 0;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const brightness = (0.299 * r + 0.587 * g + 0.114 * b); // Perceptual brightness
if (brightness > brightnessThreshold) {
const x = (i / 4) % canvas.width;
const y = Math.floor((i / 4) / canvas.width);
sumX += x;
sumY += y;
brightPixelCount++;
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
// If no bright pixels are found, return early
if (brightPixelCount === 0) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height - 50, canvas.width, 50);
ctx.font = 'bold 20px Arial';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('No flower detected', canvas.width / 2, canvas.height - 25);
return canvas;
}
const centerX = sumX / brightPixelCount;
const centerY = sumY / brightPixelCount;
const objectWidth = maxX - minX;
const objectHeight = maxY - minY;
// The maximum radius for scanning is half the smaller dimension of the detected object
const maxRadius = Math.min(objectWidth, objectHeight) / 2;
// 3. Perform circular scans at different radii to count petals
const petalCounts = [];
const scanResolution = Math.min(360, Math.floor(maxRadius * Math.PI)); // Increase resolution for larger flowers
for (let i = 0; i < scanDetail; i++) {
// Scan at radii from 30% to 90% of the max radius
const radius = maxRadius * (0.3 + 0.6 * (i / (scanDetail > 1 ? scanDetail - 1 : 1)));
if (radius < 5) continue; // Skip very small, unreliable scans
let transitions = 0;
let wasOnPetal = false;
for (let angle = 0; angle < scanResolution; angle++) {
const rad = (angle / scanResolution) * 2 * Math.PI;
const x = Math.round(centerX + radius * Math.cos(rad));
const y = Math.round(centerY + radius * Math.sin(rad));
if (x < 0 || x >= canvas.width || y < 0 || y >= canvas.height) continue;
const pixelIndex = (y * canvas.width + x) * 4;
const r = data[pixelIndex];
const g = data[pixelIndex + 1];
const b = data[pixelIndex + 2];
const brightness = (0.299 * r + 0.587 * g + 0.114 * b);
const isOnPetal = brightness > brightnessThreshold;
// If we just moved onto a petal, count it as a transition
if (isOnPetal && !wasOnPetal) {
transitions++;
}
wasOnPetal = isOnPetal;
}
petalCounts.push(transitions);
}
// 4. Find the median of the collected counts for a robust estimate
let finalPetalCount;
if (petalCounts.length > 0) {
petalCounts.sort((a, b) => a - b);
const mid = Math.floor(petalCounts.length / 2);
finalPetalCount = petalCounts.length % 2 !== 0 ? petalCounts[mid] : Math.round((petalCounts[mid - 1] + petalCounts[mid]) / 2);
} else {
finalPetalCount = 0;
}
// 5. Draw the final result on the canvas
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height - 50, canvas.width, 50);
ctx.font = 'bold 24px Arial';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(`Estimated Petal Count: ${finalPetalCount}`, canvas.width / 2, canvas.height - 25);
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Petal Count Identifier is a tool designed to analyze images of flowers and estimate the number of petals present. By detecting the flower based on brightness levels and performing circular scans around its center, the tool counts transitions from darker areas to brighter ones, which correspond to petals. This functionality is particularly useful for botanists, gardeners, and enthusiasts who want to identify floral species or perform studies related to flower morphology. The output is an image with the estimated petal count displayed, providing a visual aid for analysis.