Logo addition

This commit is contained in:
2025-08-29 10:12:37 -06:00
parent 2273ef68af
commit 25ad465bf4
6 changed files with 206 additions and 132 deletions

View File

@@ -1,6 +1,7 @@
'use client';
import { useEffect, useRef, useState, useCallback } from 'react';
import { useSearchParams } from 'next/navigation';
import { Camera, History, VideoOff, Settings, Video } from 'lucide-react';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
@@ -17,6 +18,9 @@ import type { DetectionResult, DetectionConfig } from '@/lib/ml/types';
type CameraStatus = 'loading' | 'active' | 'denied' | 'no_devices';
export default function HomePage() {
const searchParams = useSearchParams();
const isDev = searchParams.get('dev') === 'true';
const videoRef = useRef<HTMLVideoElement>(null);
const [stream, setStream] = useState<MediaStream | null>(null);
const [cameraStatus, setCameraStatus] = useState<CameraStatus>('loading');
@@ -371,13 +375,82 @@ export default function HomePage() {
<>
<video ref={videoRef} autoPlay playsInline muted onCanPlay={() => videoRef.current?.play()} className="h-full w-full object-cover" />
{/* Detection Counters */}
<div className="absolute top-4 right-4 bg-black/60 backdrop-blur-sm rounded-lg px-3 py-2 text-white text-xs space-y-1">
<div className="text-green-400">👟 Shoes Found: {shoeDetectionCount}</div>
<div className="text-gray-400">🔄 Inference Runs: {metrics?.detectionCount || 0}</div>
<div className="text-blue-400"> Avg Speed: {metrics?.inferenceTime ? `${metrics.inferenceTime.toFixed(0)}ms` : 'N/A'}</div>
{/* Impuls Logo - Top Left */}
<div className="absolute top-3 left-6 z-10 pointer-events-none">
<img
src="/Impuls Logo.png"
alt="Impuls Logo"
className="h-12 w-auto opacity-80"
style={{ filter: 'brightness(0) invert(1)' }}
/>
</div>
{/* Simple Camera Frame Overlay - Like Reference Image */}
<div className="absolute inset-0 pointer-events-none">
{/* Simple Corner Frames */}
<div className="absolute inset-0">
{/* Top Left Corner */}
<div className="absolute w-8 h-8" style={{ top: '30%', left: '25%' }}>
<div className="absolute top-0 left-0 w-6 h-0.5 bg-white opacity-80"></div>
<div className="absolute top-0 left-0 w-0.5 h-6 bg-white opacity-80"></div>
</div>
{/* Top Right Corner */}
<div className="absolute w-8 h-8" style={{ top: '30%', right: '25%' }}>
<div className="absolute top-0 right-0 w-6 h-0.5 bg-white opacity-80"></div>
<div className="absolute top-0 right-0 w-0.5 h-6 bg-white opacity-80"></div>
</div>
{/* Bottom Left Corner */}
<div className="absolute w-8 h-8" style={{ bottom: '45%', left: '25%' }}>
<div className="absolute bottom-0 left-0 w-6 h-0.5 bg-white opacity-80"></div>
<div className="absolute bottom-0 left-0 w-0.5 h-6 bg-white opacity-80"></div>
</div>
{/* Bottom Right Corner */}
<div className="absolute w-8 h-8" style={{ bottom: '45%', right: '25%' }}>
<div className="absolute bottom-0 right-0 w-6 h-0.5 bg-white opacity-80"></div>
<div className="absolute bottom-0 right-0 w-0.5 h-6 bg-white opacity-80"></div>
</div>
</div>
{/* Center Rotating 3D Shoe Logo */}
<div className="absolute w-16 h-16" style={{ top: '42.5%', left: '50%', transform: 'translate(-50%, -50%)' }}>
{/* 3D Rotating Shoe Logo */}
<div className="relative w-full h-full" style={{
transformStyle: 'preserve-3d',
animation: 'rotate3D 6s infinite linear'
}}>
{/* Shoe Logo Image */}
<img
src="/zapatillas.png"
alt="Shoe Logo"
className="absolute inset-0 w-full h-full object-contain opacity-60"
style={{ filter: 'brightness(0) invert(1)' }}
/>
</div>
</div>
{/* 3D Animation Keyframes */}
<style jsx>{`
@keyframes rotate3D {
0% { transform: rotateY(0deg) rotateX(0deg); }
25% { transform: rotateY(90deg) rotateX(15deg); }
50% { transform: rotateY(180deg) rotateX(0deg); }
75% { transform: rotateY(270deg) rotateX(-15deg); }
100% { transform: rotateY(360deg) rotateX(0deg); }
}
`}</style>
</div>
{/* Detection Counters - Only show in dev mode */}
{isDev && (
<div className="absolute top-4 right-4 bg-black/60 backdrop-blur-sm rounded-lg px-3 py-2 text-white text-xs space-y-1">
<div className="text-green-400">👟 Shoes Found: {shoeDetectionCount}</div>
<div className="text-gray-400">🔄 Inference Runs: {metrics?.detectionCount || 0}</div>
<div className="text-blue-400"> Avg Speed: {metrics?.inferenceTime ? `${metrics.inferenceTime.toFixed(0)}ms` : 'N/A'}</div>
</div>
)}
{/* Settings Panel */}
<div className={`absolute left-0 top-0 bottom-0 w-80 bg-black/80 backdrop-blur-xl border-r border-white/20 transform transition-transform duration-500 ease-out z-40 ${
@@ -422,139 +495,140 @@ export default function HomePage() {
<div className="space-y-4 flex-1">
{/* ML Detection Settings */}
<div className="bg-white/5 rounded-lg p-4 border border-white/10">
<div className="flex items-center gap-2 mb-3">
<Camera size={20} className="text-blue-400" />
<span className="text-white font-medium">Detección IA</span>
{isMLLoading && <span className="text-xs text-yellow-400">Cargando...</span>}
</div>
<div className="space-y-3">
<div className="flex items-center gap-3">
<button
onClick={() => {
setDetectionEnabled(!detectionEnabled);
if (!detectionEnabled) {
console.log('Enabling ML detection');
} else {
console.log('Disabling ML detection');
stopContinuous();
}
}}
className={`text-sm py-2 px-4 rounded-md transition-colors border ${
detectionEnabled
? 'bg-green-500/20 text-green-300 border-green-500/30 hover:bg-green-500/30'
: 'bg-white/10 text-white border-white/20 hover:bg-blue-500/30'
}`}
>
{detectionEnabled ? 'Activado' : 'Activar'}
</button>
<div className="flex items-center gap-2">
{detectionEnabled && (
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
)}
<span className="text-white/60 text-sm">
{detectionEnabled ? 'Detectando zapatos automáticamente' : 'Click para activar detección IA'}
</span>
</div>
{/* ML Detection Settings - Only show in dev mode */}
{isDev && (
<div className="bg-white/5 rounded-lg p-4 border border-white/10">
<div className="flex items-center gap-2 mb-3">
<Camera size={20} className="text-blue-400" />
<span className="text-white font-medium">Detección IA</span>
{isMLLoading && <span className="text-xs text-yellow-400">Cargando...</span>}
</div>
{/* ML Metrics */}
{detectionEnabled && metrics && (
<div className="text-xs space-y-1 text-white/50 bg-black/20 p-2 rounded">
<div>FPS: {metrics.fps.toFixed(1)}</div>
<div>Inferencia: {metrics.inferenceTime.toFixed(0)}ms</div>
{metrics.memoryUsage > 0 && <div>Memoria: {metrics.memoryUsage.toFixed(0)}MB</div>}
<div className="space-y-3">
<div className="flex items-center gap-3">
<button
onClick={() => {
setDetectionEnabled(!detectionEnabled);
if (!detectionEnabled) {
console.log('Enabling ML detection');
} else {
console.log('Disabling ML detection');
stopContinuous();
}
}}
className={`text-sm py-2 px-4 rounded-md transition-colors border ${
detectionEnabled
? 'bg-green-500/20 text-green-300 border-green-500/30 hover:bg-green-500/30'
: 'bg-white/10 text-white border-white/20 hover:bg-blue-500/30'
}`}
>
{detectionEnabled ? 'Activado' : 'Activar'}
</button>
<div className="flex items-center gap-2">
{detectionEnabled && (
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
)}
<span className="text-white/60 text-sm">
{detectionEnabled ? 'Detectando zapatos automáticamente' : 'Click para activar detección IA'}
</span>
</div>
</div>
)}
{/* ML Metrics */}
{detectionEnabled && metrics && (
<div className="text-xs space-y-1 text-white/50 bg-black/20 p-2 rounded">
<div>FPS: {metrics.fps.toFixed(1)}</div>
<div>Inferencia: {metrics.inferenceTime.toFixed(0)}ms</div>
{metrics.memoryUsage > 0 && <div>Memoria: {metrics.memoryUsage.toFixed(0)}MB</div>}
</div>
)}
{/* Detection Confidence Indicator */}
{detectionEnabled && currentDetection && (
<div className="space-y-2 pt-2">
<label className="text-sm font-medium text-white/80">Confianza de Detección</label>
<div className="bg-white/10 rounded-lg p-3 border border-white/20">
<div className="flex justify-between items-center mb-1">
<span className="text-xs text-white/60">Confianza</span>
<span className="text-xs text-white font-bold">{(currentDetection.confidence * 100).toFixed(1)}%</span>
{/* Detection Confidence Indicator */}
{detectionEnabled && currentDetection && (
<div className="space-y-2 pt-2">
<label className="text-sm font-medium text-white/80">Confianza de Detección</label>
<div className="bg-white/10 rounded-lg p-3 border border-white/20">
<div className="flex justify-between items-center mb-1">
<span className="text-xs text-white/60">Confianza</span>
<span className="text-xs text-white font-bold">{(currentDetection.confidence * 100).toFixed(1)}%</span>
</div>
<div className="w-full bg-black/30 rounded-full h-2">
<div
className={`h-2 rounded-full transition-all duration-300 ${
currentDetection.confidence > 0.8 ? 'bg-green-500' :
currentDetection.confidence > 0.6 ? 'bg-yellow-500' : 'bg-red-500'
}`}
style={{ width: `${currentDetection.confidence * 100}%` }}
/>
</div>
<div className="flex justify-between text-xs text-white/40 mt-1">
<span>Bajo</span>
<span>Alto</span>
</div>
</div>
<div className="w-full bg-black/30 rounded-full h-2">
<div
className={`h-2 rounded-full transition-all duration-300 ${
currentDetection.confidence > 0.8 ? 'bg-green-500' :
currentDetection.confidence > 0.6 ? 'bg-yellow-500' : 'bg-red-500'
}`}
style={{ width: `${currentDetection.confidence * 100}%` }}
</div>
)}
{/* Other settings */}
{detectionEnabled && config && (
<div className="space-y-4 pt-4">
<div>
<label className="text-sm font-medium text-white/80">Sensibilidad ({(config.confidenceThreshold * 100).toFixed(0)}%)</label>
<Slider
min={0.3}
max={0.9}
step={0.05}
value={[config.confidenceThreshold]}
onValueChange={([value]) => updateConfig({ confidenceThreshold: value })}
disabled={!detectionEnabled}
className="mt-2"
/>
</div>
<div className="flex justify-between text-xs text-white/40 mt-1">
<span>Bajo</span>
<span>Alto</span>
<div>
<label className="text-sm font-medium text-white/80">Frames a saltar ({config.frameSkip})</label>
<Slider
min={1}
max={10}
step={1}
value={[config.frameSkip]}
onValueChange={([value]) => updateConfig({ frameSkip: value })}
disabled={!detectionEnabled}
className="mt-2"
/>
</div>
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-white/80">Detección continua</label>
<Switch
checked={config.enableContinuous}
onCheckedChange={(checked) => updateConfig({ enableContinuous: checked })}
disabled={!detectionEnabled}
/>
</div>
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-white/80">Detección por trigger</label>
<Switch
checked={config.enableTrigger}
onCheckedChange={(checked) => updateConfig({ enableTrigger: checked })}
disabled={!detectionEnabled}
/>
</div>
</div>
</div>
)}
{/* Other settings */}
{detectionEnabled && config && (
<div className="space-y-4 pt-4">
<div>
<label className="text-sm font-medium text-white/80">Sensibilidad ({(config.confidenceThreshold * 100).toFixed(0)}%)</label>
<Slider
min={0.3}
max={0.9}
step={0.05}
value={[config.confidenceThreshold]}
onValueChange={([value]) => updateConfig({ confidenceThreshold: value })}
disabled={!detectionEnabled}
className="mt-2"
/>
)}
{/* Detection Status */}
{currentDetection && (
<div className="text-xs bg-green-500/10 text-green-300 p-2 rounded border border-green-500/20">
🎯 Zapato detectado (confianza: {(currentDetection.confidence * 100).toFixed(1)}%)
</div>
<div>
<label className="text-sm font-medium text-white/80">Frames a saltar ({config.frameSkip})</label>
<Slider
min={1}
max={10}
step={1}
value={[config.frameSkip]}
onValueChange={([value]) => updateConfig({ frameSkip: value })}
disabled={!detectionEnabled}
className="mt-2"
/>
)}
{mlError && (
<div className="text-xs bg-red-500/10 text-red-300 p-2 rounded border border-red-500/20">
{mlError}
</div>
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-white/80">Detección continua</label>
<Switch
checked={config.enableContinuous}
onCheckedChange={(checked) => updateConfig({ enableContinuous: checked })}
disabled={!detectionEnabled}
/>
</div>
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-white/80">Detección por trigger</label>
<Switch
checked={config.enableTrigger}
onCheckedChange={(checked) => updateConfig({ enableTrigger: checked })}
disabled={!detectionEnabled}
/>
</div>
</div>
)}
{/* Detection Status */}
{currentDetection && (
<div className="text-xs bg-green-500/10 text-green-300 p-2 rounded border border-green-500/20">
🎯 Zapato detectado (confianza: {(currentDetection.confidence * 100).toFixed(1)}%)
</div>
)}
{mlError && (
<div className="text-xs bg-red-500/10 text-red-300 p-2 rounded border border-red-500/20">
{mlError}
</div>
)}
)}
</div>
</div>
</div>
)}
{/* App Info */}

View File

@@ -44,14 +44,14 @@ export function getRecommendedConfig(capabilities: DeviceCapabilities): typeof D
...baseConfig,
modelVariant: 'standard',
frameSkip: 6,
confidenceThreshold: 0.6,
confidenceThreshold: 0.8,
};
case 'mid':
return {
...baseConfig,
modelVariant: 'standard',
frameSkip: 6,
confidenceThreshold: 0.5,
confidenceThreshold: 0.8,
};
case 'low':
default:
@@ -59,7 +59,7 @@ export function getRecommendedConfig(capabilities: DeviceCapabilities): typeof D
...baseConfig,
modelVariant: 'quantized',
frameSkip: 6,
confidenceThreshold: 0.4,
confidenceThreshold: 0.8,
};
}
}

View File

@@ -33,7 +33,7 @@ export const MODEL_VARIANTS: Record<'quantized' | 'standard' | 'full', ModelInfo
*/
export const DEFAULT_CONFIG: DetectionConfig = {
frameSkip: 6,
confidenceThreshold: 0.3, // Match the working implementation (30%)
confidenceThreshold: 0.8, // Default to 80% confidence
modelVariant: 'standard',
maxDetections: 5, // Match the working implementation (process up to 5 detections)
inputSize: [300, 300], // Match the working implementation

BIN
public/Impuls Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
public/Impuls Logo_.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
public/zapatillas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB