"use client"; import { motion } from "framer-motion"; import { useEffect, useState } from "react"; import { COLORS } from "./common"; import { useReducedMotion } from "@/lib/hooks/useReducedMotion"; type Sample = { src: string; alt: string; // First entry is the predicted label (highest confidence). Probabilities // must sum to (approximately) 1. probs: { label: string; p: number }[]; }; const SAMPLES: Sample[] = [ { src: "/team/01.jpg", alt: "team member 1", probs: [ { label: "que mulher maravilhosa (UAU)", p: 0.94 }, { label: "readstone", p: 0.030 }, { label: "modelo de comercial de shampoo", p: 0.012 }, { label: "sereia", p: 0.011 }, { label: "engenheira da computação", p: 0.007 }, ], }, { src: "/team/02.jpg", alt: "team member 2", probs: [ { label: "frutinha++", p: 0.91 }, { label: "morango maduro", p: 0.040 }, { label: "compota artesanal", p: 0.025 }, { label: "smoothie de açaí", p: 0.015 }, { label: "fruta exótica", p: 0.010 }, ], }, { src: "/team/03.jpg", alt: "team member 3", probs: [ { label: "homens extremamente atraentes", p: 0.96 }, { label: "testosterona", p: 0.018 }, { label: "hardware", p: 0.012 }, { label: "modelos", p: 0.006 }, { label: "gambiarra", p: 0.004 }, ], }, { src: "/team/04.jpg", alt: "team member 4", probs: [ { label: "Jorge", p: 0.97 }, { label: "homem em flagrante", p: 0.015 }, { label: "professor disfarçado", p: 0.008 }, { label: "George Clooney brasileiro", p: 0.005 }, { label: "vendedor de seguros", p: 0.002 }, ], }, { src: "/team/05.jpg", alt: "team member 5", probs: [ { label: "boiadeira", p: 0.62 }, { label: "princesa da roça", p: 0.31 }, { label: "agro pop", p: 0.040 }, { label: "festa junina", p: 0.020 }, { label: "cowgirl", p: 0.010 }, ], }, ]; export function ClassificationDemo({ intervalMs = 5500, maxImageHeight = 360, }: { intervalMs?: number; maxImageHeight?: number; }) { const [idx, setIdx] = useState(0); const [paused, setPaused] = useState(false); const reduce = useReducedMotion(); useEffect(() => { if (paused || reduce) return; const id = setInterval( () => setIdx((i) => (i + 1) % SAMPLES.length), intervalMs, ); return () => clearInterval(id); }, [paused, reduce, intervalMs]); const sample = SAMPLES[idx]; return (
{/* Image — left 2 cols, fixed max-height to keep portrait and landscape photos at the same vertical footprint. */}
{/* Probability list — right 3 cols, auto-sized */}
predicted distribution
{sample.probs.map((row, i) => { const isTop = i === 0; const pct = row.p * 100; return (
{row.label} {pct < 10 ? pct.toFixed(1) : pct.toFixed(0)}%
); })}
softmax over a class vocabulary — argmax wins
{/* Thumbnail strip + pause */}
{SAMPLES.map((_, i) => (
); }