Skip to content

Latest commit

 

History

History
551 lines (489 loc) · 15.2 KB

File metadata and controls

551 lines (489 loc) · 15.2 KB

Arwes Implementation Guide: Facial Analysis Platform

1. Arwes Setup & Configuration

Installation (Latest Versions)

# Create Next.js project
npx create-next-app@latest facial-analysis-frontend --typescript --tailwind --app

# Install Arwes and dependencies
npm install @arwes/core@latest @arwes/sounds@latest @arwes/animated@latest
npm install @arwes/react-animator@latest @arwes/react-bgs@latest
npm install howler  # For audio system
npm install socket.io-client zustand

# Additional utilities
npm install clsx tailwind-merge class-variance-authority

Arwes Theme Configuration

// lib/arwes-theme.ts
import { ArwesTheme, createArwesTheme } from '@arwes/core'

export const roboticsTheme: ArwesTheme = createArwesTheme({
  settings: {
    hue: 180, // Cyan base hue
    saturation: 100,
    luminosity: 50
  },
  colors: {
    primary: { main: '#00F8FF' },
    secondary: { main: '#0080FF' },
    success: { main: '#00FF41' },
    error: { main: '#FF0040' },
    warning: { main: '#FF8800' },
    text: { 
      root: '#FFFFFF',
      primary: '#00F8FF',
      secondary: '#CCCCCC'
    },
    bg: {
      primary: '#000000',
      secondary: '#111111'
    }
  },
  typography: {
    fontFamily: '"Titillium Web", "Roboto Mono", monospace'
  },
  space: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32
  },
  outline: {
    width: 1,
    color: '#00F8FF'
  }
})

Root Layout with Arwes Provider

// app/layout.tsx
'use client'

import { ArwesThemeProvider, BleepsProvider } from '@arwes/core'
import { AnimatorGeneralProvider } from '@arwes/react-animator'
import { roboticsTheme } from '@/lib/arwes-theme'
import { createBleepsSettings } from '@/lib/arwes-sounds'
import './globals.css'

const bleepsSettings = createBleepsSettings()

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className="bg-black text-white font-mono">
        <ArwesThemeProvider theme={roboticsTheme}>
          <BleepsProvider {...bleepsSettings}>
            <AnimatorGeneralProvider>
              {children}
            </AnimatorGeneralProvider>
          </BleepsProvider>
        </ArwesThemeProvider>
      </body>
    </html>
  )
}

2. Core Arwes Components for Facial Analysis

Main Application Frame

// components/arwes/app-frame.tsx
'use client'

import { Frame, Text, Animator } from '@arwes/core'
import { Dots, Circuit } from '@arwes/react-bgs'

interface AppFrameProps {
  children: React.ReactNode
}

export function AppFrame({ children }: AppFrameProps) {
  return (
    <div className="min-h-screen bg-black relative overflow-hidden">
      {/* Animated background */}
      <div className="absolute inset-0">
        <Dots color="#00F8FF" size={1} distance={100} />
        <Circuit color="#0080FF" lineWidth={1} />
      </div>
      
      {/* Main frame */}
      <Animator>
        <Frame
          corners={4}
          hover
          className="relative z-10 m-4 h-[calc(100vh-2rem)]"
        >
          <div className="p-6 h-full flex flex-col">
            {/* Header */}
            <header className="mb-6">
              <Text as="h1" className="text-3xl font-bold text-center">
                FACIAL ANALYSIS SYSTEM
              </Text>
              <Text className="text-center text-cyan-400 mt-2">
                Real-time Computer Vision Demo
              </Text>
            </header>
            
            {/* Content */}
            <main className="flex-1">
              {children}
            </main>
          </div>
        </Frame>
      </Animator>
    </div>
  )
}

Camera Feed Component with Arwes Styling

// components/camera/arwes-camera-feed.tsx
'use client'

import { useRef, useEffect, useState } from 'react'
import { Frame, Text, LoadingBars } from '@arwes/core'
import { Animator } from '@arwes/react-animator'
import { useBleeps } from '@arwes/sounds'

export function ArwesCameraFeed() {
  const videoRef = useRef<HTMLVideoElement>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const bleeps = useBleeps()

  useEffect(() => {
    initializeCamera()
  }, [])

  const initializeCamera = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { width: 1280, height: 720 }
      })
      
      if (videoRef.current) {
        videoRef.current.srcObject = stream
        setIsLoading(false)
        bleeps.success?.play() // Play success sound
      }
    } catch (err) {
      setError('Camera access denied')
      setIsLoading(false)
      bleeps.error?.play() // Play error sound
    }
  }

  if (error) {
    return (
      <Animator>
        <Frame corners={4} className="p-4 border-red-500">
          <Text className="text-red-400 text-center">
            {error}
          </Text>
        </Frame>
      </Animator>
    )
  }

  return (
    <div className="relative">
      <Animator>
        <Frame 
          corners={4} 
          hover
          className="overflow-hidden"
          style={{ aspectRatio: '16/9' }}
        >
          {isLoading ? (
            <div className="flex items-center justify-center h-full">
              <LoadingBars />
              <Text className="ml-4">Initializing Camera...</Text>
            </div>
          ) : (
            <video
              ref={videoRef}
              autoPlay
              playsInline
              muted
              className="w-full h-full object-cover"
            />
          )}
        </Frame>
      </Animator>
      
      {/* Scanning overlay effect */}
      <div className="absolute inset-0 pointer-events-none">
        <div className="absolute inset-0 bg-gradient-to-b from-transparent via-cyan-500/10 to-transparent animate-pulse" />
      </div>
    </div>
  )
}

Face Detection Overlay with Arwes Effects

// components/analysis/arwes-face-overlay.tsx
'use client'

import { Frame, Text } from '@arwes/core'
import { Animator } from '@arwes/react-animator'
import { useBleeps } from '@arwes/sounds'
import { useEffect } from 'react'

interface Face {
  id: string
  bbox: [number, number, number, number]
  confidence: number
}

interface ArwesFaceOverlayProps {
  faces: Face[]
}

export function ArwesFaceOverlay({ faces }: ArwesFaceOverlayProps) {
  const bleeps = useBleeps()

  useEffect(() => {
    if (faces.length > 0) {
      bleeps.click?.play() // Play detection sound
    }
  }, [faces.length, bleeps])

  return (
    <div className="absolute inset-0 pointer-events-none">
      {faces.map((face) => (
        <Animator key={face.id}>
          <div
            className="absolute"
            style={{
              left: face.bbox[0],
              top: face.bbox[1],
              width: face.bbox[2] - face.bbox[0],
              height: face.bbox[3] - face.bbox[1],
            }}
          >
            <Frame
              corners={4}
              hover={false}
              className="w-full h-full border-cyan-400"
              style={{
                borderWidth: 2,
                boxShadow: '0 0 20px rgba(0, 248, 255, 0.5)'
              }}
            >
              {/* Confidence indicator */}
              <div className="absolute -top-8 left-0">
                <Text className="text-xs bg-black/80 px-2 py-1 rounded">
                  {Math.round(face.confidence * 100)}%
                </Text>
              </div>
              
              {/* Corner markers */}
              <div className="absolute -top-1 -left-1 w-4 h-4 border-l-2 border-t-2 border-cyan-400" />
              <div className="absolute -top-1 -right-1 w-4 h-4 border-r-2 border-t-2 border-cyan-400" />
              <div className="absolute -bottom-1 -left-1 w-4 h-4 border-l-2 border-b-2 border-cyan-400" />
              <div className="absolute -bottom-1 -right-1 w-4 h-4 border-r-2 border-b-2 border-cyan-400" />
            </Frame>
          </div>
        </Animator>
      ))}
    </div>
  )
}

Analysis Results Panel

// components/analysis/arwes-results-panel.tsx
'use client'

import { Frame, Text, Table, LoadingBars } from '@arwes/core'
import { Animator } from '@arwes/react-animator'
import { useBleeps } from '@arwes/sounds'

interface AnalysisResult {
  age: number
  gender: string
  emotions: Record<string, number>
  confidence: number
}

interface ArwesResultsPanelProps {
  results: AnalysisResult[]
  isProcessing: boolean
}

export function ArwesResultsPanel({ results, isProcessing }: ArwesResultsPanelProps) {
  const bleeps = useBleeps()

  const getTopEmotion = (emotions: Record<string, number>) => {
    return Object.entries(emotions).reduce((a, b) => 
      emotions[a[0]] > emotions[b[0]] ? a : b
    )[0]
  }

  return (
    <div className="space-y-4">
      <Animator>
        <Frame corners={4} hover className="p-4">
          <Text as="h2" className="text-xl mb-4 text-cyan-400">
            ANALYSIS RESULTS
          </Text>
          
          {isProcessing ? (
            <div className="flex items-center space-x-4">
              <LoadingBars />
              <Text>Processing facial data...</Text>
            </div>
          ) : results.length === 0 ? (
            <Text className="text-gray-400">
              No faces detected. Position yourself in front of the camera.
            </Text>
          ) : (
            <div className="space-y-4">
              {results.map((result, index) => (
                <Animator key={index}>
                  <Frame corners={2} className="p-3 bg-gray-900/50">
                    <div className="grid grid-cols-2 gap-4">
                      <div>
                        <Text className="text-sm text-cyan-400">AGE</Text>
                        <Text className="text-2xl font-bold">{result.age}</Text>
                      </div>
                      <div>
                        <Text className="text-sm text-cyan-400">GENDER</Text>
                        <Text className="text-lg">{result.gender}</Text>
                      </div>
                      <div>
                        <Text className="text-sm text-cyan-400">EMOTION</Text>
                        <Text className="text-lg capitalize">
                          {getTopEmotion(result.emotions)}
                        </Text>
                      </div>
                      <div>
                        <Text className="text-sm text-cyan-400">CONFIDENCE</Text>
                        <Text className="text-lg">
                          {Math.round(result.confidence * 100)}%
                        </Text>
                      </div>
                    </div>
                  </Frame>
                </Animator>
              ))}
            </div>
          )}
        </Frame>
      </Animator>
    </div>
  )
}

3. Arwes Sound System Configuration

Sound Effects Setup

// lib/arwes-sounds.ts
import { BleepsSettings } from '@arwes/sounds'

export const createBleepsSettings = (): BleepsSettings => ({
  master: { volume: 0.3 },
  categories: {
    background: { volume: 0.1 },
    transition: { volume: 0.5 },
    interaction: { volume: 0.7 }
  },
  bleeps: {
    // System sounds
    startup: {
      category: 'transition',
      sources: [{ src: '/sounds/startup.mp3' }]
    },
    click: {
      category: 'interaction',
      sources: [{ src: '/sounds/click.mp3' }]
    },
    success: {
      category: 'interaction',
      sources: [{ src: '/sounds/success.mp3' }]
    },
    error: {
      category: 'interaction',
      sources: [{ src: '/sounds/error.mp3' }]
    },
    // Analysis-specific sounds
    faceDetected: {
      category: 'interaction',
      sources: [{ src: '/sounds/face-detected.mp3' }]
    },
    analysisComplete: {
      category: 'interaction',
      sources: [{ src: '/sounds/analysis-complete.mp3' }]
    },
    // Loading page sounds
    irisActivation: {
      category: 'transition',
      sources: [{ src: '/sounds/iris-activation.mp3' }]
    },
    systemOnline: {
      category: 'transition',
      sources: [{ src: '/sounds/system-online.mp3' }]
    },
    scanningBeep: {
      category: 'interaction',
      sources: [{ src: '/sounds/scanning-beep.mp3' }]
    },
    // Background ambience
    ambience: {
      category: 'background',
      sources: [{ src: '/sounds/sci-fi-ambience.mp3' }],
      loop: true
    }
  }
})

4. Complete Page Implementation

Main Application Page

// app/page.tsx
'use client'

import { useState, useEffect } from 'react'
import { AppFrame } from '@/components/arwes/app-frame'
import { ArwesCameraFeed } from '@/components/camera/arwes-camera-feed'
import { ArwesFaceOverlay } from '@/components/analysis/arwes-face-overlay'
import { ArwesResultsPanel } from '@/components/analysis/arwes-results-panel'
import { useWebSocket } from '@/hooks/use-websocket'
import { useBleeps } from '@arwes/sounds'

export default function HomePage() {
  const [faces, setFaces] = useState([])
  const [analysisResults, setAnalysisResults] = useState([])
  const [isProcessing, setIsProcessing] = useState(false)
  const bleeps = useBleeps()
  
  const { socket, isConnected } = useWebSocket('ws://localhost:5000')

  useEffect(() => {
    if (socket) {
      socket.on('face_detected', (data) => {
        setFaces(data.faces)
        bleeps.faceDetected?.play()
      })
      
      socket.on('analysis_complete', (data) => {
        setAnalysisResults(data.results)
        setIsProcessing(false)
        bleeps.analysisComplete?.play()
      })
      
      socket.on('processing_started', () => {
        setIsProcessing(true)
      })
    }
  }, [socket, bleeps])

  useEffect(() => {
    // Play startup sound when component mounts
    bleeps.startup?.play()
    bleeps.ambience?.play()
    
    return () => {
      bleeps.ambience?.stop()
    }
  }, [bleeps])

  return (
    <AppFrame>
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6 h-full">
        {/* Camera Feed */}
        <div className="lg:col-span-2 relative">
          <ArwesCameraFeed />
          <ArwesFaceOverlay faces={faces} />
        </div>
        
        {/* Analysis Panel */}
        <div className="lg:col-span-1">
          <ArwesResultsPanel 
            results={analysisResults} 
            isProcessing={isProcessing} 
          />
        </div>
      </div>
    </AppFrame>
  )
}

5. Arwes Advantages for Robotics Club

Why Arwes is Perfect for This Project:

  1. Authentic Sci-Fi Aesthetic: Purpose-built for futuristic interfaces
  2. Built-in Animations: Smooth enter/exit transitions without additional libraries
  3. Sound System: Integrated audio feedback enhances the tech demo experience
  4. Accessibility: WCAG compliant while maintaining futuristic styling
  5. Performance: Optimized for real-time applications
  6. Customization: Highly themeable for club branding
  7. Mobile Responsive: Works great on tablets for portable demos

Demo Impact:

  • Visual Appeal: Immediately recognizable as advanced technology
  • Audio Feedback: Sound effects make interactions feel responsive
  • Professional Look: Gives the impression of enterprise-grade software
  • Memorable Experience: Unique aesthetic creates lasting impressions
  • Social Media Ready: Highly shareable futuristic interface

This Arwes implementation will create an impressive, professional-looking facial analysis platform that perfectly showcases your robotics club's technical capabilities!