{"id":28922163,"url":"https://github.com/seeed-solution/face-recognition-api","last_synced_at":"2025-10-12T20:40:24.750Z","repository":{"id":300173048,"uuid":"1004780133","full_name":"Seeed-Solution/face-recognition-api","owner":"Seeed-Solution","description":"Based on the Hailo-8 AI accelerator, providing a 512-dimension face embedding vector generation API.","archived":false,"fork":false,"pushed_at":"2025-06-20T07:31:55.000Z","size":23411,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-05T07:51:51.034Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Seeed-Solution.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-19T07:03:54.000Z","updated_at":"2025-06-20T07:31:58.000Z","dependencies_parsed_at":"2025-06-20T08:46:21.835Z","dependency_job_id":null,"html_url":"https://github.com/Seeed-Solution/face-recognition-api","commit_stats":null,"previous_names":["seeed-solution/face-recognition-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Seeed-Solution/face-recognition-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seeed-Solution%2Fface-recognition-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seeed-Solution%2Fface-recognition-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seeed-Solution%2Fface-recognition-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seeed-Solution%2Fface-recognition-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Seeed-Solution","download_url":"https://codeload.github.com/Seeed-Solution/face-recognition-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seeed-Solution%2Fface-recognition-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279012802,"owners_count":26085190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-22T07:38:19.989Z","updated_at":"2025-10-12T20:40:24.706Z","avatar_url":"https://github.com/Seeed-Solution.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FaceEmbed API\n\nThe face recognition API, also referred to as the \"FaceEmbed API\".\n\nA high-performance face feature extraction service based on the Hailo-8 AI accelerator, providing a 512-dimension face embedding vector generation API.\n\n## ✨ Features\n\n- 🚀 **High-Performance Inference**: 3-18ms latency based on Hailo-8 hardware acceleration.\n- 🎯 **Standardized Output**: 512-dimension, L2-normalized face embedding vectors.\n- 🔄 **Asynchronous Processing**: Supports both single and batch image processing.\n- ✨ **All-in-One Detection \u0026 Embedding**: A single endpoint for face detection, alignment, and feature extraction.\n- 🗄️ **Built-in Vector Database**: Includes a self-contained SQLite database for vector storage and search, eliminating external dependencies.\n- 📊 **Comprehensive Tests**: 28 test cases with 100% pass rate.\n- 🌐 **Cross-Origin Support**: Enables access from clients like Node-RED on different machines.\n\n## 🏗️ Project Structure\n\n```\nface_embed_api/\n├── 📂 src/                         # Core source code\n│   ├── app.py                      # FastAPI application\n│   ├── database.py                 # SQLite database management\n│   └── utils.py                    # Hailo inference utilities\n│   └── __init__.py                 # Package initializer\n├── 📂 data/                        # Data storage\n│   └── vectors.db                  # SQLite database file\n├── 📂 tests/                       # Test suite\n│   ├── unit/                       # Unit tests\n│   └── integration/                # Integration tests\n├── 📂 scripts/                     # Utility scripts\n│   ├── start_server.py             # Start the server\n│   ├── run_tests.py                # Run tests\n│   └── test_hailo_request.py       # API test script\n├── 📂 models/                      # AI model files\n├── 📂 docs/                        # Documentation\n└── 📂 logs/                        # Runtime logs\n```\n\n## 🚀 Quick Start\n\n### 1. Environment Setup\n\n```bash\n# Activate the virtual environment\nsource .venv/bin/activate\n\n# Install base dependencies\nuv sync\n```\n\n### 2. Hailo-8 Hardware Configuration (Required)\n\n**Important**: This service requires Hailo-8 hardware. Please follow these steps for configuration:\n\n1.  **Download HailoRT**: Visit the [Hailo Developer Zone](https://hailo.ai/developer-zone/software-downloads/) to download the necessary files.\n2.  **System Configuration**: Refer to the [Hailo Setup Guide](docs/HAILO_SETUP.md) for detailed instructions.\n3.  **Verify Installation**: Use test scripts to ensure the hardware is working correctly.\n\n**Required Components**:\n- Raspberry Pi 5 + Hailo-8 AI Kit\n- HailoRT 4.21.0 (System packages + Python package)\n- PCIe drivers and configuration\n- Face recognition model file (arcface_mobilefacenet.hef)\n- Face detection model file (scrfd_10g.hef)\n\n### 3. Start the Service\n\n```bash\n# Set PYTHONPATH and start with uvicorn (recommended)\nPYTHONPATH=src uv run uvicorn src.app:app --host 0.0.0.0 --port 8000\n```\n\n### 4. Verify the Service\n\n```bash\n# Health check\ncurl http://localhost:8000/health\n\n# API test\n# (Please refer to the API examples below for testing)\n```\n\n## 📋 API Endpoints\n\n### Health Check\n```http\nGET /health\n```\n**Response**:\n```json\n{\n  \"status\": \"ok\",\n  \"uptime_ms\": 12345,\n  \"loaded_models\": [\"scrfd_10g.hef\", \"arcface_mobilefacenet.hef\"]\n}\n```\n\n### Vector Database Endpoints\n\nThese endpoints manage the internal SQLite vector database.\n\n#### Add a Vector\n```http\nPOST /vectors/add\nContent-Type: application/json\n\n{\n  \"collection\": \"office_entrance\",\n  \"user_id\": \"user_001\",\n  \"vector\": [0.1, 0.2, \"...\"]\n}\n```\n\n#### Search for a Vector\n```http\nPOST /vectors/search\nContent-Type: application/json\n\n{\n  \"collection\": \"office_entrance\",\n  \"vector\": [0.11, 0.22, \"...\"],\n  \"threshold\": 0.32\n}\n```\n\n#### Delete a User's Vectors\n```http\nPOST /vectors/delete\nContent-Type: application/json\n\n{\n  \"collection\": \"office_entrance\",\n  \"user_id\": \"user_001\"\n}\n```\n\n### All-in-One Detection and Embedding\nThis endpoint performs both face detection and feature extraction in a single request. It is the **recommended** primary endpoint for recognition.\n\n```http\nPOST /detect_and_embed\nContent-Type: application/json\n\n{\n  \"image_base64\": \"base64_encoded_image\",\n  \"confidence_threshold\": 0.5\n}\n```\n**Response**:\n```json\n[\n  {\n    \"bbox\": { \"x\": 50, \"y\": 50, \"w\": 100, \"h\": 120 },\n    \"landmarks\": [\n      {\"x\": 70, \"y\": 70},\n      {\"x\": 130, \"y\": 70},\n      {\"x\": 100, \"y\": 100},\n      {\"x\": 80, \"y\": 130},\n      {\"x\": 120, \"y\": 130}\n    ],\n    \"detection_confidence\": 0.98,\n    \"embedding\": {\n      \"vector\": [0.1, 0.2, \"...\"],\n      \"processing_time_ms\": 15,\n      \"confidence\": 0.95\n    }\n  }\n]\n```\n\n### Single Face Embedding (Manual Mode)\nThis endpoint requires you to provide the bounding box (bbox) and landmarks for the face.\n\n```http\nPOST /embed\nContent-Type: application/json\n\n{\n  \"image_base64\": \"base64_encoded_image\",\n  \"bbox\": {\"x\": 50, \"y\": 50, \"w\": 100, \"h\": 120},\n  \"landmarks\": [\n      {\"x\": 70, \"y\": 70},\n      {\"x\": 130, \"y\": 70},\n      {\"x\": 100, \"y\": 100},\n      {\"x\": 80, \"y\": 130},\n      {\"x\": 120, \"y\": 130}\n  ]\n}\n```\n\n### Batch Face Embedding (Manual Mode)\n```http\nPOST /batch_embed\nContent-Type: application/json\n\n{\n  \"images\": [\n    {\n      \"image_base64\": \"base64_encoded_image\",\n      \"bbox\": {\"x\": 50, \"y\": 50, \"w\": 100, \"h\": 120}\n    }\n  ]\n}\n```\n\n## 🧪 Testing\n\n### Run All Tests\n```bash\nuv run -- pytest -v\n```\n\n### Run Tests Individually\n```bash\n# Unit tests\npytest tests/unit/ -v\n\n# Integration tests\npytest tests/integration/ -v\n```\n\n## 🐛 Debugging\n\nThis service includes a built-in image debugging feature that saves key images from the processing pipeline to the local disk, making it easier to analyze and troubleshoot issues.\n\n### How to Enable\n\nEnable debugging mode by setting the following environment variables:\n\n```bash\nexport DEBUG_SAVE_IMAGES=true\nexport DEBUG_SAVE_INTERVAL_S=5 # Save one image at most every 5 seconds to prevent disk flooding\n\n# Then start the service\nPYTHONPATH=src uv run uvicorn app:app --host 0.0.0.0 --port 8000\n```\n\n### Debug Environment Variables\n\n- **`DEBUG_SAVE_IMAGES`**: Set to `true`, `1`, or `t` to enable image saving.\n- **`DEBUG_SAVE_INTERVAL_S`**: Controls the minimum time interval (in seconds) between saving images. Default is `10`. This helps prevent generating excessive files when processing video streams or large batches of requests.\n\n### Saved Image Types\n\nWhen enabled, the following types of images will be saved to the `debug_images/` folder in the project root:\n\n- **`detected_*.jpg`**: The original image with face detection boxes and landmarks drawn on it.\n- **`cropped_for_embedding_*.jpg`**: The **unaligned** face image cropped from the original, pre-processed for the embedding model.\n- **`aligned_for_embedding_*.jpg`**: The face image after being aligned using landmarks, ready for the embedding model.\n\nFilenames include timestamps and confidence scores for easy tracking.\n\n## 🔧 Development\n\n### Adding New Features\n1. Implement the feature in `src/`.\n2. Add unit tests in `tests/unit/`.\n3. Add integration tests in `tests/integration/`.\n4. Run tests to ensure they pass.\n\n### Code Structure\n- **app.py**: FastAPI application and route definitions.\n- **utils.py**: Hailo asynchronous inference engine.\n- **tests/**: Complete test coverage.\n\n## 🛠️ Tech Stack\n\n- **API Framework**: FastAPI + Uvicorn\n- **AI Inference**: Hailo-8 + HailoAsyncInference\n- **Image Processing**: OpenCV + NumPy\n- **Testing Framework**: pytest + unittest\n- **Dependency Management**: UV\n\n## 📊 Performance Metrics\n\n- **Inference Latency**: 3-18ms (Hailo hardware)\n- **Vector Dimension**: 512-dim standard ArcFace\n- **Normalization**: L2 normalization (norm=1.0)\n- **Concurrency Support**: Asynchronous multithreading\n- **Test Coverage**: 28 tests, 100% pass rate\n\n## 🔍 API Examples\n\n### Python Client\n```python\nimport requests\nimport base64\nimport cv2\nimport numpy as np\n\n# --- Configuration ---\nBASE_URL = \"http://localhost:8000\"\nIMAGE_PATH = \"face.jpg\"  # Create a dummy image or use a real one\nCOLLECTION_NAME = \"my_office_collection\"\nUSER_ID = \"user_101\"\n\ndef image_to_base64(img_path):\n    \"\"\"Encodes an image to base64\"\"\"\n    try:\n        with open(img_path, \"rb\") as image_file:\n            return base64.b64encode(image_file.read()).decode('utf-8')\n    except FileNotFoundError:\n        print(f\"Error: Image file not found at '{img_path}'. Creating a dummy file.\")\n        dummy_img = np.zeros((200, 200, 3), dtype=np.uint8)\n        cv2.imwrite(img_path, dummy_img)\n        with open(img_path, \"rb\") as image_file:\n            return base64.b64encode(image_file.read()).decode('utf-8')\n\ndef run_full_test():\n    # 1. Health check\n    print(\"--- 1. Health Check ---\")\n    response = requests.get(f\"{BASE_URL}/health\")\n    print(f\"Status: {response.status_code}, Body: {response.json()}\")\n    response.raise_for_status()\n\n    # 2. Get a face vector\n    print(\"\\n--- 2. Detecting face and getting embedding vector ---\")\n    image_b64 = image_to_base64(IMAGE_PATH)\n    response = requests.post(\n        f\"{BASE_URL}/detect_and_embed\",\n        json={'image_base64': image_b64, 'confidence_threshold': 0.5}\n    )\n    response.raise_for_status()\n    results = response.json()\n    if not results:\n        print(\"No faces detected. Exiting.\")\n        return\n    \n    vector = results[0]['embedding']['vector']\n    print(f\"Detected {len(results)} faces. Vector obtained.\")\n\n    # 3. Add vector to DB\n    print(\"\\n--- 3. Adding vector to database ---\")\n    add_payload = {\n        \"collection\": COLLECTION_NAME,\n        \"user_id\": USER_ID,\n        \"vector\": vector\n    }\n    response = requests.post(f\"{BASE_URL}/vectors/add\", json=add_payload)\n    print(f\"Status: {response.status_code}, Body: {response.json()}\")\n    response.raise_for_status()\n\n    # 4. Search for the vector\n    print(\"\\n--- 4. Searching for the vector ---\")\n    search_payload = {\n        \"collection\": COLLECTION_NAME,\n        \"vector\": vector,\n        \"threshold\": 0.9\n    }\n    response = requests.post(f\"{BASE_URL}/vectors/search\", json=search_payload)\n    print(f\"Status: {response.status_code}, Body: {response.json()}\")\n    response.raise_for_status()\n\n    # 5. Delete the vector\n    print(\"\\n--- 5. Deleting the vector ---\")\n    delete_payload = {\n        \"collection\": COLLECTION_NAME,\n        \"user_id\": USER_ID\n    }\n    response = requests.post(f\"{BASE_URL}/vectors/delete\", json=delete_payload)\n    print(f\"Status: {response.status_code}, Body: {response.json()}\")\n    response.raise_for_status()\n\nif __name__ == '__main__':\n    run_full_test()\n```\n\n### Node-RED Integration\n```javascript\n// In a Node-RED Function node\n// This example performs detection and embedding\n// and can be chained with another function node to add the vector to the DB.\n\nconst payload = {\n    image_base64: msg.payload.image, // Assumes base64 image is in msg.payload.image\n    confidence_threshold: 0.5 // Optional\n};\n\nmsg.url = \"http://YOUR_PI_IP:8000/detect_and_embed\";\nmsg.method = \"POST\";\nmsg.headers = {\"Content-Type\": \"application/json\"};\nmsg.payload = payload;\n\nreturn msg;\n```\n\n## 📈 Deployment\n\n### Production Environment\n```bash\n# Start the service\nPYTHONPATH=src uv run uvicorn app:app --host 0.0.0.0 --port 8000\n```\n\n### Environment Variables\n- `HOST`: Service listening address (default: 0.0.0.0)\n- `PORT`: Service port (default: 8000)\n- `FACE_RECOGNITION_HEF`: Path to the face recognition model file\n- `FACE_DETECTION_HEF`: Path to the face detection model file\n- `DEBUG_SAVE_IMAGES`: Enable debug image saving (`true` / `false`)\n- `DEBUG_SAVE_INTERVAL_S`: Interval for saving debug images in seconds (default: 10)\n- `DB_FILE`: Path to the SQLite database file (default: `data/vectors.db`)\n\n## 🚨 Dependencies\n\n### Required Installations\n- **HailoRT 4.21.0**: Core inference engine\n- **Hailo-8 AI Kit**: Hardware accelerator\n- **Raspberry Pi 5**: Host board with PCIe support\n- **Face Recognition Model**: arcface_mobilefacenet.hef\n- **Face Detection Model**: scrfd_10g.hef\n\n### System Requirements\n- **OS**: Linux (Raspberry Pi OS or Ubuntu)\n- **Python**: 3.11+\n- **Memory**: 4GB+ recommended\n- **Storage**: 8GB+ available space\n\n## 📚 Documentation\n\n- [Project Structure Details](PROJECT_STRUCTURE.md)\n- [Hailo Installation Guide](docs/HAILO_SETUP.md)\n- [Hailo API Guide](docs/reference/hailo_python_guide.md)\n\n## 🤝 Contributing\n\n1. Fork the project\n2. Create a feature branch\n3. Commit your changes\n4. Push to the branch\n5. Create a Pull Request\n\n## 📄 License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeed-solution%2Fface-recognition-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseeed-solution%2Fface-recognition-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeed-solution%2Fface-recognition-api/lists"}