The reference measurement will be bust, underbust, waist, hips, height or weight in imperial or metric
3db8e08 verified Download script.js from slothmonarchy/bodymetrics-analyzer-pro: direct link, hf CLI and curl.
- Browser
- Download file 11.5 kB
-
https://huggingface.co/spaces/slothmonarchy/bodymetrics-analyzer-pro/resolve/main/script.js
- Command line
-
hf download hf://spaces/slothmonarchy/bodymetrics-analyzer-pro/script.js
-
curl -L -o script.js https://huggingface.co/spaces/slothmonarchy/bodymetrics-analyzer-pro/resolve/main/script.js
11.5 kB
| // Global variables | |
| let currentImage = null; | |
| let analysisInProgress = false; | |
| // DOM Elements | |
| const dropZone = document.getElementById('dropZone'); | |
| const imageUpload = document.getElementById('imageUpload'); | |
| const previewImage = document.getElementById('previewImage'); | |
| const resultsSection = document.getElementById('resultsSection'); | |
| const loadingSection = document.getElementById('loadingSection'); | |
| // Measurement elements | |
| const measurementElements = { | |
| bust: { value: document.getElementById('bustValue'), note: document.getElementById('bustNote') }, | |
| underbust: { value: document.getElementById('underbustValue'), note: document.getElementById('underbustNote') }, | |
| waist: { value: document.getElementById('waistValue'), note: document.getElementById('waistNote') }, | |
| hips: { value: document.getElementById('hipsValue'), note: document.getElementById('hipsNote') }, | |
| height: { value: document.getElementById('heightValue'), note: document.getElementById('heightNote') }, | |
| weight: { value: document.getElementById('weightValue'), note: document.getElementById('weightNote') } | |
| }; | |
| // Confidence elements | |
| const confidenceValue = document.getElementById('confidenceValue'); | |
| const analysisNotes = document.getElementById('analysisNotes'); | |
| // Initialize the application | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initializeEventListeners(); | |
| }); | |
| function initializeEventListeners() { | |
| // File input change | |
| imageUpload.addEventListener('change', handleFileSelect); | |
| // Drag and drop events | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, highlight, false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, unhighlight, false); | |
| }); | |
| dropZone.addEventListener('drop', handleDrop, false); | |
| } | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| function highlight() { | |
| dropZone.classList.add('drag-over'); | |
| } | |
| function unhighlight() { | |
| dropZone.classList.remove('drag-over'); | |
| } | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleFiles(files); | |
| } | |
| function handleFileSelect(e) { | |
| const files = e.target.files; | |
| handleFiles(files); | |
| } | |
| function handleFiles(files) { | |
| if (analysisInProgress) return; | |
| const file = files[0]; | |
| if (!file) return; | |
| // Check if file is an image | |
| if (!file.type.match('image.*')) { | |
| alert('Please upload an image file (JPG, PNG, WEBP)'); | |
| return; | |
| } | |
| // Check file size (10MB max) | |
| if (file.size > 10 * 1024 * 1024) { | |
| alert('File size must be less than 10MB'); | |
| return; | |
| } | |
| // Create preview | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| previewImage.src = e.target.result; | |
| currentImage = e.target.result; | |
| startAnalysis(); | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| function startAnalysis() { | |
| if (!currentImage) return; | |
| analysisInProgress = true; | |
| // Show loading state | |
| resultsSection.classList.add('hidden'); | |
| loadingSection.classList.remove('hidden'); | |
| // Get reference values | |
| const referenceType = document.getElementById('referenceType').value; | |
| const referenceValue = parseFloat(document.getElementById('referenceValue').value) || null; | |
| const unitSystem = document.getElementById('unitSystem').value; | |
| const actualHeight = parseFloat(document.getElementById('actualHeight').value) || null; | |
| const heightUnit = document.getElementById('heightUnit').value; | |
| // Simulate AI analysis (in a real app, this would call an API) | |
| setTimeout(() => { | |
| performAnalysis(referenceType, referenceValue, unitSystem, actualHeight, heightUnit); | |
| }, 3000); | |
| } | |
| function performAnalysis(referenceType, referenceValue, unitSystem, actualHeight, heightUnit) { | |
| // This is a mock analysis - in a real application, this would use computer vision APIs | |
| const measurements = generateMockMeasurements(referenceType, referenceValue, unitSystem, actualHeight, heightUnit); | |
| // Update UI with results | |
| updateResultsUI(measurements, unitSystem); | |
| // Hide loading, show results | |
| loadingSection.classList.add('hidden'); | |
| resultsSection.classList.remove('hidden'); | |
| analysisInProgress = false; | |
| } | |
| function generateMockMeasurements(referenceType, referenceValue, unitSystem, actualHeight, heightUnit) { | |
| // Convert actual height to cm for internal calculations | |
| let baseHeightCm; | |
| if (actualHeight) { | |
| baseHeightCm = heightUnit === 'in' ? actualHeight * 2.54 : actualHeight; | |
| } else { | |
| baseHeightCm = 160 + Math.random() * 30; // 160-190cm if not provided | |
| } | |
| // Base measurements in cm for metric system | |
| let baseMeasurements = { | |
| bust: (85 + Math.random() * 20) * (baseHeightCm / 170), | |
| underbust: (70 + Math.random() * 15) * (baseHeightCm / 170), | |
| waist: (65 + Math.random() * 15) * (baseHeightCm / 170), | |
| hips: (90 + Math.random() * 20) * (baseHeightCm / 170), | |
| height: baseHeightCm, | |
| weight: (55 + Math.random() * 25) * (baseHeightCm / 170) / 1.7 | |
| }; | |
| // Adjust measurements if reference is provided | |
| if (referenceValue && referenceType) { | |
| // Convert reference value to cm if needed | |
| let referenceValueCm = referenceValue; | |
| if (unitSystem === 'imperial' && referenceType !== 'weight') { | |
| referenceValueCm = referenceValue * 2.54; | |
| } else if (unitSystem === 'imperial' && referenceType === 'weight') { | |
| referenceValueCm = referenceValue * 0.453592; | |
| } | |
| // Calculate scaling factor based on reference | |
| const scalingFactor = referenceValueCm / baseMeasurements[referenceType]; | |
| // Apply scaling to all measurements | |
| Object.keys(baseMeasurements).forEach(key => { | |
| if (key !== 'weight') { | |
| baseMeasurements[key] *= scalingFactor; | |
| } else { | |
| baseMeasurements[key] *= scalingFactor; | |
| } | |
| }); | |
| } | |
| // Convert to desired unit system for display | |
| const measurements = {}; | |
| Object.keys(baseMeasurements).forEach(key => { | |
| let displayValue; | |
| let estimated = true; | |
| let confidence = 'medium'; | |
| // Determine if this measurement is accurate based on reference | |
| if (referenceType === key) { | |
| estimated = false; | |
| confidence = 'high'; | |
| } else if (referenceValue && referenceType) { | |
| confidence = 'high'; | |
| } | |
| if (unitSystem === 'metric') { | |
| if (key === 'weight') { | |
| displayValue = Math.round(baseMeasurements[key]); | |
| } else { | |
| displayValue = Math.round(baseMeasurements[key]); | |
| } | |
| } else { | |
| if (key === 'weight') { | |
| displayValue = Math.round(baseMeasurements[key] * 2.20462); | |
| } else { | |
| displayValue = Math.round(baseMeasurements[key] / 2.54 * 10) / 10; // Round to 1 decimal for inches | |
| } else { | |
| displayValue = Math.round(baseMeasurements[key]); | |
| } | |
| } | |
| measurements[key] = { | |
| value: displayValue, | |
| estimated: estimated, | |
| confidence: confidence | |
| }; | |
| }); | |
| return measurements; | |
| } | |
| function updateResultsUI(measurements, unitSystem) { | |
| // Update each measurement | |
| Object.keys(measurements).forEach(key => { | |
| const measurement = measurements[key]; | |
| const element = measurementElements[key]; | |
| if (element) { | |
| // Update value with appropriate units | |
| let unit = ''; | |
| if (key === 'weight') { | |
| unit = unitSystem === 'metric' ? 'kg' : 'lbs'; | |
| } else { | |
| unit = unitSystem === 'metric' ? 'cm' : 'in'; | |
| } | |
| element.value.textContent = `${measurement.value} ${unit}`; | |
| // Update note | |
| if (measurement.estimated) { | |
| element.note.textContent = 'Estimated value'; | |
| element.note.className = 'text-sm text-amber-600'; | |
| } else { | |
| element.note.textContent = 'Measured from reference'; | |
| element.note.className = 'text-sm text-green-600'; | |
| } | |
| } | |
| }); | |
| // Update confidence level | |
| const confidenceLevels = Object.values(measurements).map(m => m.confidence); | |
| const avgConfidence = confidenceLevels.reduce((a, b) => { | |
| const values = { low: 1, medium: 2, high: 3 }; | |
| return a + values[b]; | |
| }, 0) / confidenceLevels.length; | |
| let confidenceText = ''; | |
| let confidenceColor = ''; | |
| if (avgConfidence >= 2.5) { | |
| confidenceText = 'High'; | |
| confidenceColor = 'text-green-600'; | |
| } else if (avgConfidence >= 1.5) { | |
| confidenceText = 'Medium'; | |
| confidenceColor = 'text-amber-600'; | |
| } else { | |
| confidenceText = 'Low'; | |
| confidenceColor = 'text-red-600'; | |
| } | |
| confidenceValue.textContent = confidenceText; | |
| confidenceValue.className = `font-semibold ${confidenceColor}`; | |
| // Update analysis notes | |
| let notes = []; | |
| const referenceType = document.getElementById('referenceType').value; | |
| const referenceValue = parseFloat(document.getElementById('referenceValue').value) || null; | |
| const actualHeight = parseFloat(document.getElementById('actualHeight').value) || null; | |
| if (!referenceValue && !actualHeight) { | |
| notes.push('No reference measurement provided. Measurements are estimated based on average proportions.'); | |
| } else if (referenceValue && !actualHeight) { | |
| notes.push(`Using ${referenceType} measurement as reference. Height is estimated.`); | |
| } else if (actualHeight) { | |
| notes.push('Using provided height for proportion calculations.'); | |
| } | |
| if (measurements.weight.estimated) { | |
| notes.push('Weight is estimated based on body proportions and typical BMI ranges.'); | |
| } | |
| analysisNotes.querySelector('span').textContent = notes.join(' '); | |
| } | |
| function resetAnalysis() { | |
| // Reset file input | |
| imageUpload.value = ''; | |
| // Reset preview | |
| previewImage.src = ''; | |
| currentImage = null; | |
| // Reset measurement values | |
| Object.values(measurementElements).forEach(element => { | |
| element.value.textContent = '-- cm'; | |
| element.note.textContent = ''; | |
| element.note.className = 'text-sm text-gray-600'; | |
| }); | |
| // Reset reference inputs | |
| document.getElementById('referenceType').value = 'bust'; | |
| document.getElementById('unitSystem').value = 'metric'; | |
| document.getElementById('referenceValue').value = ''; | |
| document.getElementById('actualHeight').value = ''; | |
| document.getElementById('heightUnit').value = 'cm'; | |
| // Hide results | |
| resultsSection.classList.add('hidden'); | |
| } | |
| // Utility function to convert pixels to real measurements | |
| function pixelsToCm(pixels, referencePixels, referenceCm) { | |
| if (!referencePixels || !referenceCm) return null; | |
| return (pixels / referencePixels) * referenceCm; | |
| } |