{ "cells": [ { "cell_type": "markdown", "metadata": { "vscode": { "languageId": "plaintext" } }, "source": [ "# Face Detection and Alignment with UniFace\n", "\n", "
\n", " \"PyPI\n", " \"PyPI\n", " \"License\"\n", " \"GitHub\n", "
\n", "\n", "**UniFace** is a lightweight, production-ready Python library for face detection, recognition, tracking, landmark analysis, face parsing, gaze estimation, and face attributes.\n", "\n", "🔗 **GitHub**: [github.com/yakhyo/uniface](https://github.com/yakhyo/uniface) | 📚 **Docs**: [yakhyo.github.io/uniface](https://yakhyo.github.io/uniface)\n", "\n", "---\n", "\n", "This notebook demonstrates face detection and alignment using the **UniFace** library.\n", "\n", "## 1. Install UniFace" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install -q \"uniface[cpu]\"\n", "\n", "# Clone repo for assets (Colab only)\n", "import os\n", "if 'COLAB_GPU' in os.environ or 'COLAB_RELEASE_TAG' in os.environ:\n", " if not os.path.exists('uniface'):\n", " !git clone --depth 1 https://github.com/yakhyo/uniface.git\n", " os.chdir('uniface/examples')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Import Libraries" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import cv2\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "import uniface\n", "from uniface.detection import RetinaFace\n", "from uniface.face_utils import face_alignment\n", "from uniface.draw import draw_detections\n", "\n", "print(uniface.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Initialize the Detector" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "detector = RetinaFace(\n", " confidence_threshold=0.5,\n", " nms_threshold=0.4,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Load Images and Perform Detection + Alignment" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "image_paths = [\n", " '../assets/test_images/image0.jpg',\n", " '../assets/test_images/image1.jpg',\n", " '../assets/test_images/image2.jpg',\n", " '../assets/test_images/image3.jpg',\n", " '../assets/test_images/image4.jpg',\n", "]\n", "\n", "original_images = []\n", "detection_images = []\n", "aligned_images = []\n", "\n", "for image_path in image_paths:\n", " # Load image\n", " image = cv2.imread(image_path)\n", " if image is None:\n", " print(f'Error: Could not read {image_path}')\n", " continue\n", "\n", " # Detect faces\n", " faces = detector.detect(image)\n", " if not faces:\n", " print(f'No faces detected in {image_path}')\n", " continue\n", "\n", " # Draw detections\n", " bbox_image = image.copy()\n", " draw_detections(image=bbox_image, faces=faces, vis_threshold=0.6, corner_bbox=True)\n", "\n", " # Align first detected face (returns aligned image and inverse transform matrix)\n", " first_landmarks = faces[0].landmarks\n", " aligned_image, _ = face_alignment(image, first_landmarks, image_size=112)\n", "\n", " # Convert BGR to RGB for visualization\n", " original_images.append(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))\n", " detection_images.append(cv2.cvtColor(bbox_image, cv2.COLOR_BGR2RGB))\n", " aligned_images.append(cv2.cvtColor(aligned_image, cv2.COLOR_BGR2RGB))\n", "\n", "print(f'Processed {len(original_images)} images')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Visualize Results" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(3, len(original_images), figsize=(15, 10))\n", "\n", "row_titles = ['Original', 'Detection', 'Aligned']\n", "\n", "for row, images in enumerate([original_images, detection_images, aligned_images]):\n", " for col, img in enumerate(images):\n", " axes[row, col].imshow(img)\n", " axes[row, col].axis('off')\n", " if col == 0:\n", " axes[row, col].set_title(row_titles[row], fontsize=12, loc='left')\n", "\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Notes\n", "\n", "- `detect()` returns a list of `Face` objects with `bbox`, `confidence`, `landmarks` attributes\n", "- Access attributes using dot notation: `face.bbox`, `face.landmarks`\n", "- `face_alignment()` uses 5-point landmarks to align and crop the face\n", "- Default output size is 112x112 (standard for face recognition models)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.5" } }, "nbformat": 4, "nbformat_minor": 2 }