{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example Usage of UniFace Library\n",
    "This guide demonstrates how to use the **UniFace** library for face detection and visualization in this Jupyter Notebook. Follow the steps below to set up and execute the example.\n",
    "\n",
    "## 1. Install UniFace\n",
    "Install the **UniFace** library using `pip`. The `-q` flag suppresses logs for a clean output."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q uniface"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Import Required Libraries\n",
    "Import the necessary libraries for image processing and visualization:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "from PIL import Image\n",
    "import IPython.display as display\n",
    "from uniface import RetinaFace, draw_detections\n",
    "from uniface.constants import RetinaFaceWeights"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `cv2`: Used for image reading and processing.\n",
    "- `PIL`: For displaying images inline in the notebook.\n",
    "- `display`: To render PIL images within the notebook.\n",
    "- `RetinaFace`: The model class from the **UniFace** library.\n",
    "- `draw_detections`: A utility function to draw bounding boxes and landmarks on the image.\n",
    "\n",
    "## 3. Initialize the RetinaFace Model\n",
    "Initialize the RetinaFace model with a lightweight pre-trained backbone and detection parameters:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-03-26 11:43:28,753 - INFO - Initializing RetinaFace with model=RetinaFaceWeights.MNET_V2, conf_thresh=0.5, nms_thresh=0.4, pre_nms_topk=5000, post_nms_topk=750, dynamic_size=False, input_size=(640, 640)\n",
      "2025-03-26 11:43:28,753 - INFO - Downloading model 'RetinaFaceWeights.MNET_V2' from https://github.com/yakhyo/uniface/releases/download/v0.1.2/retinaface_mv2.onnx\n",
      "2025-03-26 11:43:31,322 - INFO - Successfully downloaded 'RetinaFaceWeights.MNET_V2' to C:\\Users\\yakhyo\\.uniface\\models\\RetinaFaceWeights.MNET_V2.onnx\n",
      "2025-03-26 11:43:31,334 - INFO - Verified model weights located at: C:\\Users\\yakhyo/.uniface/models\\RetinaFaceWeights.MNET_V2.onnx\n",
      "2025-03-26 11:43:31,393 - INFO - Successfully initialized the model from C:\\Users\\yakhyo/.uniface/models\\RetinaFaceWeights.MNET_V2.onnx\n"
     ]
    }
   ],
   "source": [
    "# Initialize the RetinaFace model\n",
    "uniface_inference = RetinaFace(\n",
    "    model_name=RetinaFaceWeights.MNET_V2,   # Model name\n",
    "    conf_thresh=0.5,                        # Confidence threshold\n",
    "    pre_nms_topk=5000,                      # Pre-NMS Top-K detections\n",
    "    nms_thresh=0.4,                         # NMS IoU threshold\n",
    "    post_nms_topk=750                       # Post-NMS Top-K detections,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Load and Display the Input Image\n",
    "Load an image using PIL to display it inline before performing inference:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 147632 characters]",
      "image/png": "[encoded data, 1470668 characters]",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1024x624>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image_path = \"../assets/test.jpg\"\n",
    "pil_image = Image.open(image_path)\n",
    "pil_image"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Perform Inference and Display Results\n",
    "Run the face detection inference and display the processed image with bounding boxes and landmarks:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 162640 characters]",
      "image/png": "[encoded data, 1479168 characters]",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=1024x624>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Load an image\n",
    "original_image = cv2.imread(image_path)\n",
    "\n",
    "# Perform inference\n",
    "boxes, landmarks = uniface_inference.detect(original_image)\n",
    "\n",
    "# Visualize results\n",
    "draw_detections(original_image, (boxes, landmarks), vis_threshold=0.6)\n",
    "\n",
    "# Convert BGR to RGB for correct color rendering\n",
    "output_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)\n",
    "\n",
    "# Use PIL to display the image in the notebook\n",
    "output_pil = Image.fromarray(output_image)\n",
    "display.display(output_pil)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## We can also detect only top-k faces\n",
    "- To detect only top-k faces, we need to pass `max_num` parameter.\n",
    "\n",
    "### top-2 faces"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 148916 characters]",
      "image/png": "[encoded data, 1471256 characters]",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=1024x624>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Load an image\n",
    "original_image = cv2.imread(image_path)\n",
    "\n",
    "# Perform inference\n",
    "boxes, landmarks = uniface_inference.detect(original_image, max_num=2)\n",
    "\n",
    "# Visualize results\n",
    "draw_detections(original_image, (boxes, landmarks), vis_threshold=0.6)\n",
    "\n",
    "# Convert BGR to RGB for correct color rendering\n",
    "output_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)\n",
    "\n",
    "# Use PIL to display the image in the notebook\n",
    "output_pil = Image.fromarray(output_image)\n",
    "display.display(output_pil)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### top-5 faces"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "[encoded data, 150476 characters]",
      "image/png": "[encoded data, 1472488 characters]",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=1024x624>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Load an image\n",
    "original_image = cv2.imread(image_path)\n",
    "\n",
    "# Perform inference\n",
    "boxes, landmarks = uniface_inference.detect(original_image, max_num=5)\n",
    "\n",
    "# Visualize results\n",
    "draw_detections(original_image, (boxes, landmarks), vis_threshold=0.6)\n",
    "\n",
    "# Convert BGR to RGB for correct color rendering\n",
    "output_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)\n",
    "\n",
    "# Use PIL to display the image in the notebook\n",
    "output_pil = Image.fromarray(output_image)\n",
    "display.display(output_pil)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Key Notes:\n",
    "- Ensure that the **image path** (`../assets/test.jpg`) points to a valid image file.\n",
    "- Adjust detection thresholds (`conf_thresh`, `nms_thresh`) in **RetinaFace** for specific use cases.\n",
    "- Use the **draw_detections** function to easily visualize the results on the processed image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "uniface",
   "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.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
