Spaces:
Sleeping
Sleeping
| const express = require('express'); | |
| const faceapi = require('face-api.js'); | |
| const canvas = require('canvas'); | |
| const { Canvas, Image, ImageData } = canvas; | |
| const fileUpload = require('express-fileupload'); | |
| const path = require('path'); | |
| const app = express(); | |
| // Enable CORS for all origins | |
| app.use((req, res, next) => { | |
| res.header('Access-Control-Allow-Origin', '*'); | |
| res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); | |
| res.header('Access-Control-Allow-Headers', 'Content-Type'); | |
| if (req.method === 'OPTIONS') { | |
| return res.sendStatus(200); | |
| } | |
| next(); | |
| }); | |
| app.use(fileUpload()); | |
| faceapi.env.monkeyPatch({ Canvas, Image, ImageData }); | |
| // Model dosyalarının yolu | |
| // Model files are in root directory on HF Spaces | |
| const MODEL_PATH = __dirname; | |
| // Modelleri yükleme | |
| async function loadModels() { | |
| try { | |
| await Promise.all([ | |
| faceapi.nets.ssdMobilenetv1.loadFromDisk(MODEL_PATH), | |
| faceapi.nets.faceLandmark68Net.loadFromDisk(MODEL_PATH), | |
| faceapi.nets.faceRecognitionNet.loadFromDisk(MODEL_PATH), | |
| faceapi.nets.faceExpressionNet.loadFromDisk(MODEL_PATH), | |
| faceapi.nets.ageGenderNet.loadFromDisk(MODEL_PATH), | |
| ]); | |
| console.log('Face-api.js models loaded.'); | |
| } catch (err) { | |
| console.error('Error loading models:', err); | |
| throw err; | |
| } | |
| } | |
| // Health check endpoint (for Hugging Face Spaces) | |
| app.get('/', (req, res) => { | |
| res.json({ | |
| status: 'healthy', | |
| service: 'Face Analysis API', | |
| endpoints: { | |
| predict: '/predict_face (POST)' | |
| }, | |
| models: 'face-api.js (SSD MobileNet V1)' | |
| }); | |
| }); | |
| // Sunucuyu başlatmadan önce modelleri yükle | |
| loadModels().then(() => { | |
| const PORT = process.env.PORT || 5001; | |
| app.listen(PORT, () => { | |
| console.log(`Face analysis server running on port ${PORT}`); | |
| }); | |
| }).catch(err => { | |
| console.error('Failed to start server due to model loading error:', err); | |
| }); | |
| app.post('/predict_face', async (req, res) => { | |
| if (!req.files || !req.files.image) { | |
| return res.status(400).json({ error: 'No image provided' }); | |
| } | |
| const file = req.files.image; | |
| try { | |
| // Görüntüyü canvas'a yükle | |
| const img = await canvas.loadImage(file.data); | |
| const origWidth = img.width; | |
| const origHeight = img.height; | |
| // Görüntüyü analiz et (orijinal boyutlarda) | |
| const detections = await faceapi | |
| .detectAllFaces(img) | |
| .withFaceLandmarks() | |
| .withFaceExpressions() | |
| .withAgeAndGender(); | |
| if (detections.length === 0) { | |
| return res.status(400).json({ error: 'No face detected' }); | |
| } | |
| // Sonuç objesini oluştur | |
| const result = detections.map(d => { | |
| // Koordinatları orijinal boyutlara göre döndür (face-api.js zaten orijinal boyutları kullanır) | |
| const box = { | |
| x: d.detection.box.x, | |
| y: d.detection.box.y, | |
| width: d.detection.box.width, | |
| height: d.detection.box.height, | |
| }; | |
| const landmarks = d.landmarks.positions.map(position => ({ | |
| x: position.x, | |
| y: position.y, | |
| })); | |
| return { | |
| age: Math.round(d.age), | |
| gender: d.gender, | |
| genderProbability: d.genderProbability, | |
| expressions: d.expressions, | |
| detection: { box }, | |
| landmarks, | |
| imageDimensions: { width: origWidth, height: origHeight }, // Orijinal boyutları ekle | |
| }; | |
| }); | |
| // Loglama: Backend'den gönderilen boyutları ve koordinatları kontrol et | |
| console.log('Backend Image Dimensions:', result[0].imageDimensions); | |
| console.log('Backend Detection Box:', result[0].detection.box); | |
| console.log('Backend Landmarks Sample:', result[0].landmarks.slice(0, 5)); // İlk 5 landmark | |
| res.json(result[0]); // İlk yüzü döndür | |
| } catch (err) { | |
| console.error('Face analysis error:', err); | |
| res.status(500).json({ error: 'Face analysis failed', details: err.message }); | |
| } | |
| }); | |
| module.exports = app; |