Skip to content

Commit

Permalink
Move library into own folder
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthijsBurgh committed Jun 13, 2024
1 parent c2221a5 commit ce754fd
Show file tree
Hide file tree
Showing 37 changed files with 105 additions and 95 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
run: |
python --version
echo "import tests.actions_test" > test.py
coverage run --source models,examples test.py
coverage run --source facenet_pytorch/models,examples tests/actions_test.py
coverage report
coverage xml
- name: Upload coverage to Codecov
Expand Down
54 changes: 28 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Face Recognition Using Pytorch
# Face Recognition Using Pytorch

*You can also read a translated version of this file [in Chinese 简体中文版](README_cn.md).*

![banner](static/facenet-pytorch-banner.png)

[![Downloads](https://pepy.tech/badge/facenet-pytorch)](https://pepy.tech/project/facenet-pytorch)

[![Code Coverage](https://img.shields.io/codecov/c/github/timesler/facenet-pytorch.svg)](https://codecov.io/gh/timesler/facenet-pytorch)
Expand All @@ -18,12 +20,12 @@ Also included in this repo is an efficient pytorch implementation of MTCNN for f
* [Quick start](#quick-start)
* [Pretrained models](#pretrained-models)
* [Example notebooks](#example-notebooks)
+ [*Complete detection and recognition pipeline*](#complete-detection-and-recognition-pipeline)
+ [*Face tracking in video streams*](#face-tracking-in-video-streams)
+ [*Finetuning pretrained models with new data*](#finetuning-pretrained-models-with-new-data)
+ [*Guide to MTCNN in facenet-pytorch*](#guide-to-mtcnn-in-facenet-pytorch)
+ [*Performance comparison of face detection packages*](#performance-comparison-of-face-detection-packages)
+ [*The FastMTCNN algorithm*](#the-fastmtcnn-algorithm)
* [*Complete detection and recognition pipeline*](#complete-detection-and-recognition-pipeline)
* [*Face tracking in video streams*](#face-tracking-in-video-streams)
* [*Finetuning pretrained models with new data*](#finetuning-pretrained-models-with-new-data)
* [*Guide to MTCNN in facenet-pytorch*](#guide-to-mtcnn-in-facenet-pytorch)
* [*Performance comparison of face detection packages*](#performance-comparison-of-face-detection-packages)
* [*The FastMTCNN algorithm*](#the-fastmtcnn-algorithm)
* [Running with docker](#running-with-docker)
* [Use this repo in your own git project](#use-this-repo-in-your-own-git-project)
* [Conversion of parameters from Tensorflow to Pytorch](#conversion-of-parameters-from-tensorflow-to-pytorch)
Expand All @@ -32,7 +34,7 @@ Also included in this repo is an efficient pytorch implementation of MTCNN for f
## Quick start

1. Install:

```bash
# With pip:
pip install facenet-pytorch
Expand All @@ -43,10 +45,10 @@ Also included in this repo is an efficient pytorch implementation of MTCNN for f
# or use a docker container (see https://github.com/timesler/docker-jupyter-dl-gpu):
docker run -it --rm timesler/jupyter-dl-gpu pip install facenet-pytorch && ipython
```

1. In python, import facenet-pytorch and instantiate models:
```python

```py
from facenet_pytorch import MTCNN, InceptionResnetV1
# If required, create a face detection pipeline using MTCNN:
Expand All @@ -55,10 +57,10 @@ Also included in this repo is an efficient pytorch implementation of MTCNN for f
# Create an inception resnet (in eval mode):
resnet = InceptionResnetV1(pretrained='vggface2').eval()
```

1. Process an image:
```python

```py
from PIL import Image
img = Image.open(<image path>)
Expand All @@ -78,7 +80,7 @@ See `help(MTCNN)` and `help(InceptionResnetV1)` for usage and implementation det

## Pretrained models

See: [models/inception_resnet_v1.py](models/inception_resnet_v1.py)
See: [models/inception_resnet_v1.py](facenet_pytorch/models/inception_resnet_v1.py)

The following models have been ported to pytorch (with links to download pytorch state_dict's):
Expand All @@ -89,7 +91,7 @@ The following models have been ported to pytorch (with links to download pytorch
There is no need to manually download the pretrained state_dict's; they are downloaded automatically on model instantiation and cached for future use in the torch cache. To use an Inception Resnet (V1) model for facial recognition/identification in pytorch, use:

```python
```py
from facenet_pytorch import InceptionResnetV1
# For a model pretrained on VGGFace2
Expand Down Expand Up @@ -119,7 +121,7 @@ Face recognition can be easily applied to raw images by first detecting faces us

MTCNN can be used to build a face tracking system (using the `MTCNN.detect()` method). A full face tracking example can be found at [examples/face_tracking.ipynb](examples/face_tracking.ipynb).
![](examples/tracked.gif)
![Tracking](examples/tracked.gif)
### *Finetuning pretrained models with new data*
Expand Down Expand Up @@ -156,7 +158,7 @@ Each package is tested for its speed in detecting the faces in a set of 300 imag
|dlib|3.80|8.39|14.53|
|mtcnn|3.04|5.70|8.23|
![](examples/performance-comparison.png)
![Performance comparison](examples/performance-comparison.png)
See the [notebook on kaggle](https://www.kaggle.com/timesler/comparison-of-face-detection-packages).
Expand Down Expand Up @@ -193,9 +195,9 @@ Alternatively, the code can be installed as a package using pip:
## Conversion of parameters from Tensorflow to Pytorch
See: [models/utils/tensorflow2pytorch.py](models/tensorflow2pytorch.py)
See: [models/utils/tensorflow2pytorch.py](facenet_pytorch/models/tensorflow2pytorch.py)
Note that this functionality is not needed to use the models in this repo, which depend only on the saved pytorch `state_dict`'s.
Note that this functionality is not needed to use the models in this repo, which depend only on the saved pytorch `state_dict`'s.
Following instantiation of the pytorch model, each layer's weights were loaded from equivalent layers in the pretrained tensorflow models from [davidsandberg/facenet](https://github.com/davidsandberg/facenet).
Expand All @@ -205,7 +207,7 @@ The equivalence of the outputs from the original tensorflow models and the pytor
`>>> compare_model_outputs(mdl, sess, torch.randn(5, 160, 160, 3).detach())`
```
```py
Passing test data through TF model
tensor([[-0.0142, 0.0615, 0.0057, ..., 0.0497, 0.0375, -0.0838],
Expand All @@ -228,16 +230,16 @@ Distance 1.2874517096861382e-06
---
In order to re-run the conversion of tensorflow parameters into the pytorch model, ensure you clone this repo _with submodules_, as the davidsandberg/facenet repo is included as a submodule and parts of it are required for the conversion.
In order to re-run the conversion of tensorflow parameters into the pytorch model, ensure you clone this repo *with submodules_, as the davidsandberg/facenet repo is included as a submodule and parts of it are required for the conversion.
## References
1. David Sandberg's facenet repo: [https://github.com/davidsandberg/facenet](https://github.com/davidsandberg/facenet)
1. F. Schroff, D. Kalenichenko, J. Philbin. _FaceNet: A Unified Embedding for Face Recognition and Clustering_, arXiv:1503.03832, 2015. [PDF](https://arxiv.org/pdf/1503.03832)
1. F. Schroff, D. Kalenichenko, J. Philbin. *FaceNet: A Unified Embedding for Face Recognition and Clustering_, arXiv:1503.03832, 2015. [PDF](https://arxiv.org/pdf/1503.03832)
1. Q. Cao, L. Shen, W. Xie, O. M. Parkhi, A. Zisserman. _VGGFace2: A dataset for recognising face across pose and age_, International Conference on Automatic Face and Gesture Recognition, 2018. [PDF](http://www.robots.ox.ac.uk/~vgg/publications/2018/Cao18/cao18.pdf)
1. Q. Cao, L. Shen, W. Xie, O. M. Parkhi, A. Zisserman. *VGGFace2: A dataset for recognising face across pose and age_, International Conference on Automatic Face and Gesture Recognition, 2018. [PDF](http://www.robots.ox.ac.uk/~vgg/publications/2018/Cao18/cao18.pdf)
1. D. Yi, Z. Lei, S. Liao and S. Z. Li. _CASIAWebface: Learning Face Representation from Scratch_, arXiv:1411.7923, 2014. [PDF](https://arxiv.org/pdf/1411.7923)
1. D. Yi, Z. Lei, S. Liao and S. Z. Li. *CASIAWebface: Learning Face Representation from Scratch_, arXiv:1411.7923, 2014. [PDF](https://arxiv.org/pdf/1411.7923)
1. K. Zhang, Z. Zhang, Z. Li and Y. Qiao. _Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks_, IEEE Signal Processing Letters, 2016. [PDF](https://kpzhang93.github.io/MTCNN_face_detection_alignment/paper/spl.pdf)
1. K. Zhang, Z. Zhang, Z. Li and Y. Qiao. *Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks_, IEEE Signal Processing Letters, 2016. [PDF](https://kpzhang93.github.io/MTCNN_face_detection_alignment/paper/spl.pdf)
4 changes: 2 additions & 2 deletions README_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ img_probs = resnet(img_cropped.unsqueeze(0))

## 预训练模型

请参阅:[models/inception_resnet_v1.py](models/inception_resnet_v1.py)
请参阅:[models/inception_resnet_v1.py](facenet_pytorch/models/inception_resnet_v1.py)

以下模型已移植到 pytorch(包含下载 pytorch state_dict 的链接):

Expand Down Expand Up @@ -233,7 +233,7 @@ docker run --rm -p 8888:8888

## Tensorflow 到 Pytorch 的参数转换

请参阅:[models/utils/tensorflow2pytorch.py](models/tensorflow2pytorch.py)
请参阅:[models/utils/tensorflow2pytorch.py](facenet_pytorch/models/tensorflow2pytorch.py)

请注意,使用此存储库中的模型不需要此功能,该功能仅依赖于pytorch保存的 `state_dict`

Expand Down
12 changes: 0 additions & 12 deletions __init__.py

This file was deleted.

3 changes: 0 additions & 3 deletions data/.gitignore

This file was deleted.

1 change: 1 addition & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tmptest.py
14 changes: 8 additions & 6 deletions examples/finetune.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"from facenet_pytorch import MTCNN, InceptionResnetV1, fixed_image_standardization, training\n",
"import torch\n",
"from torch.utils.data import DataLoader, SubsetRandomSampler\n",
Expand All @@ -41,7 +42,8 @@
"metadata": {},
"outputs": [],
"source": [
"data_dir = '../data/test_images'\n",
"root_dir = Path(__file__).parent.parent\n",
"data_dir = root_dir / \"tests\" / \"data\" / \"test_images\"\n",
"\n",
"batch_size = 32\n",
"epochs = 8\n",
Expand Down Expand Up @@ -106,19 +108,19 @@
"source": [
"dataset = datasets.ImageFolder(data_dir, transform=transforms.Resize((512, 512)))\n",
"dataset.samples = [\n",
" (p, p.replace(data_dir, data_dir + '_cropped'))\n",
" (p, p.replace(str(data_dir), str(data_dir.parent / (data_dir.name + \"_aligned\"))))\n",
" for p, _ in dataset.samples\n",
"]\n",
" \n",
"\n",
"loader = DataLoader(\n",
" dataset,\n",
" num_workers=workers,\n",
" batch_size=batch_size,\n",
" collate_fn=training.collate_pil\n",
")\n",
"\n",
"for i, (x, y) in enumerate(loader):\n",
" mtcnn(x, save_path=y)\n",
"for i, (input_file, output_file) in enumerate(loader):\n",
" mtcnn(input_file, save_path=output_file)\n",
" print('\\rBatch {} of {}'.format(i + 1, len(loader)), end='')\n",
" \n",
"# Remove mtcnn to reduce GPU memory usage\n",
Expand Down Expand Up @@ -168,7 +170,7 @@
" transforms.ToTensor(),\n",
" fixed_image_standardization\n",
"])\n",
"dataset = datasets.ImageFolder(data_dir + '_cropped', transform=trans)\n",
"dataset = datasets.ImageFolder(data_dir.parent / (data_dir.name + \"_aligned\"), transform=trans)\n",
"img_inds = np.arange(len(dataset))\n",
"np.random.shuffle(img_inds)\n",
"train_inds = img_inds[:int(0.8 * len(img_inds))]\n",
Expand Down
8 changes: 5 additions & 3 deletions examples/finetune_cn.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"from facenet_pytorch import MTCNN, InceptionResnetV1, fixed_image_standardization, training\n",
"import torch\n",
"from torch.utils.data import DataLoader, SubsetRandomSampler\n",
Expand All @@ -41,7 +42,8 @@
"metadata": {},
"outputs": [],
"source": [
"data_dir = '../data/test_images'\n",
"root_dir = Path(__file__).parent.parent\n",
"data_dir = root_dir / \"tests\" / \"data\" / \"test_images\"\n",
"\n",
"batch_size = 32\n",
"epochs = 8\n",
Expand Down Expand Up @@ -106,7 +108,7 @@
"source": [
"dataset = datasets.ImageFolder(data_dir, transform=transforms.Resize((512, 512)))\n",
"dataset.samples = [\n",
" (p, p.replace(data_dir, data_dir + '_cropped'))\n",
" (p, p.replace(str(data_dir), str(data_dir.parent / (data_dir.name + \"_aligned\"))))\n",
" for p, _ in dataset.samples\n",
"]\n",
" \n",
Expand Down Expand Up @@ -168,7 +170,7 @@
" transforms.ToTensor(),\n",
" fixed_image_standardization\n",
"])\n",
"dataset = datasets.ImageFolder(data_dir + '_cropped', transform=trans)\n",
"dataset = datasets.ImageFolder(data_dir + '_aligned', transform=trans)\n",
"img_inds = np.arange(len(dataset))\n",
"np.random.shuffle(img_inds)\n",
"train_inds = img_inds[:int(0.8 * len(img_inds))]\n",
Expand Down
12 changes: 8 additions & 4 deletions examples/infer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import os\n",
"\n",
"from facenet_pytorch import MTCNN, InceptionResnetV1\n",
"import torch\n",
"from torch.utils.data import DataLoader\n",
"from torchvision import datasets\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"\n",
"workers = 0 if os.name == 'nt' else 4"
]
Expand Down Expand Up @@ -118,7 +119,10 @@
"def collate_fn(x):\n",
" return x[0]\n",
"\n",
"dataset = datasets.ImageFolder('../data/test_images')\n",
"root_dir = Path(__file__).parent.parent\n",
"data_dir = root_dir / \"tests\" / \"data\" / \"test_images\"\n",
"\n",
"dataset = datasets.ImageFolder(data_dir)\n",
"dataset.idx_to_class = {i:c for c, i in dataset.class_to_idx.items()}\n",
"loader = DataLoader(dataset, collate_fn=collate_fn, num_workers=workers)"
]
Expand Down Expand Up @@ -242,4 +246,4 @@
},
"nbformat": 4,
"nbformat_minor": 2
}
}
10 changes: 7 additions & 3 deletions examples/infer_cn.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@
},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import os\n",
"\n",
"from facenet_pytorch import MTCNN, InceptionResnetV1\n",
"import torch\n",
"from torch.utils.data import DataLoader\n",
"from torchvision import datasets\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"\n",
"workers = 0 if os.name == 'nt' else 4"
]
Expand Down Expand Up @@ -144,7 +145,10 @@
"def collate_fn(x):\n",
" return x[0]\n",
"\n",
"dataset = datasets.ImageFolder('../data/test_images')\n",
"root_dir = Path(__file__).parent.parent\n",
"data_dir = root_dir / \"tests\" / \"data\" / \"test_images\"\n",
"\n",
"dataset = datasets.ImageFolder(data_dir)\n",
"dataset.idx_to_class = {i:c for c, i in dataset.class_to_idx.items()}\n",
"loader = DataLoader(dataset, collate_fn=collate_fn, num_workers=workers)"
]
Expand Down
8 changes: 4 additions & 4 deletions examples/lfw_evaluate.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
"box_probs = []\n",
"\n",
"for i, (x, b_paths) in enumerate(loader):\n",
" crops = [p.replace(data_dir, data_dir + '_cropped') for p in b_paths]\n",
" crops = [p.replace(str(data_dir), str(data_dir.parent / (data_dir.name + \"_aligned\"))) for p in b_paths]\n",
" mtcnn(x, save_path=crops)\n",
" crop_paths.extend(crops)\n",
" print('\\rBatch {} of {}'.format(i + 1, len(loader)), end='')"
Expand Down Expand Up @@ -176,7 +176,7 @@
" fixed_image_standardization\n",
"])\n",
"\n",
"dataset = datasets.ImageFolder(data_dir + '_cropped', transform=trans)\n",
"dataset = datasets.ImageFolder(data_dir.parent / data_dir.name + \"_aligned\", transform=trans)\n",
"\n",
"embed_loader = DataLoader(\n",
" dataset,\n",
Expand Down Expand Up @@ -452,7 +452,7 @@
"outputs": [],
"source": [
"pairs = read_pairs(pairs_path)\n",
"path_list, issame_list = get_paths(data_dir+'_cropped', pairs)\n",
"path_list, issame_list = get_paths(data_dir+'_aligned', pairs)\n",
"embeddings = np.array([embeddings_dict[path] for path in path_list])\n",
"\n",
"tpr, fpr, accuracy, val, val_std, far, fp, fn = evaluate(embeddings, issame_list)"
Expand Down Expand Up @@ -519,4 +519,4 @@
},
"nbformat": 4,
"nbformat_minor": 0
}
}
Loading

0 comments on commit ce754fd

Please sign in to comment.