anjith2006 commited on
Commit
5f4b8c4
Β·
verified Β·
1 Parent(s): d9c7817

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +186 -0
README.md ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: edgeface-idiap
4
+ license_link: https://gitlab.idiap.ch/bob/bob.paper.tbiom2023_edgeface/-/blob/master/LICENSE
5
+ library_name: transformers
6
+ pipeline_tag: image-feature-extraction
7
+ tags:
8
+ - face-recognition
9
+ - face-verification
10
+ - face-embedding
11
+ - edgeface
12
+ - timm
13
+ ---
14
+
15
+ # EdgeFace for πŸ€— Transformers
16
+
17
+ [EdgeFace](https://arxiv.org/abs/2307.01838) (Idiap Research Institute) packaged as a `transformers` custom model. All four published variants live in this single repository as subfolders and are accessible through the standard `AutoModel` / `AutoImageProcessor` API with built-in MediaPipe face alignment.
18
+
19
+ EdgeFace replaces the classifier of an `edgenext` (timm) backbone with a 512-d embedding head trained for face recognition. Two variants additionally apply a static low-rank factorization to their linear layers β€” EdgeFace's "gamma" trick, baked into the pretrained weights and unrelated to PEFT adapters.
20
+
21
+ ## Model variants
22
+
23
+ | Subfolder | Backbone | Low-rank ratio | Params |
24
+ |---|---|---|---|
25
+ | `edgeface-base` | `edgenext_base` | β€” | ~18 M |
26
+ | `edgeface-s-gamma-05` | `edgenext_small` | 0.5 | ~5 M |
27
+ | `edgeface-xs-gamma-06` | `edgenext_x_small` | 0.6 | ~3 M |
28
+ | `edgeface-xxs` | `edgenext_xx_small` | β€” | ~1 M |
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install transformers timm torch safetensors huggingface_hub numpy
34
+
35
+ # Face alignment (do_align=True) also requires:
36
+ pip install mediapipe opencv-python
37
+ ```
38
+
39
+ ## Quick start
40
+
41
+ ```python
42
+ import torch
43
+ import torch.nn.functional as F
44
+ from PIL import Image
45
+ from transformers import AutoModel, AutoImageProcessor
46
+
47
+ repo = "anjith2006/edgeface"
48
+ variant = "edgeface-xxs" # or edgeface-base / edgeface-s-gamma-05 / edgeface-xs-gamma-06
49
+
50
+ model = AutoModel.from_pretrained(repo, subfolder=variant, trust_remote_code=True).eval()
51
+ processor = AutoImageProcessor.from_pretrained(repo, subfolder=variant, trust_remote_code=True)
52
+
53
+ @torch.no_grad()
54
+ def embed(path):
55
+ img = Image.open(path).convert("RGB")
56
+ inputs = processor(img, return_tensors="pt") # do_align=True by default
57
+ return F.normalize(model(**inputs).embeddings, dim=-1)
58
+
59
+ score = F.cosine_similarity(embed("a.jpg"), embed("b.jpg")).item()
60
+ print(f"{score:.4f}") # β†’ ~0.9+ same person, lower for different
61
+ ```
62
+
63
+ ## Face alignment
64
+
65
+ The image processor detects and aligns the face by default, warping it onto the ArcFace 112Γ—112 template using 5 MediaPipe landmarks β€” the same alignment the weights were trained with.
66
+
67
+ ```python
68
+ # Full image β†’ detect face, align, normalize (default)
69
+ inputs = processor(img, return_tensors="pt")
70
+
71
+ # Pre-aligned 112Γ—112 crop β†’ skip detection, just normalize
72
+ inputs = processor(crop, do_align=False, return_tensors="pt")
73
+
74
+ # Known landmarks β†’ skip detection, align from provided 5 points
75
+ inputs = processor(img, landmarks=pts, return_tensors="pt") # pts: ndarray (5, 2)
76
+ ```
77
+
78
+ If detection fails the processor falls back to a plain resize so batches never crash.
79
+
80
+ ### MediaPipe backend
81
+
82
+ ```python
83
+ # "auto" (default): try the Tasks API, fall back to legacy solutions.face_mesh
84
+ # "tasks": force the modern API β€” downloads face_landmarker.task once to ~/.cache/edgeface/
85
+ # "solutions": force the legacy API (older mediapipe installs)
86
+ processor = AutoImageProcessor.from_pretrained(
87
+ repo, subfolder=variant, trust_remote_code=True, mp_backend="tasks"
88
+ )
89
+
90
+ # Offline / custom bundle:
91
+ processor = AutoImageProcessor.from_pretrained(
92
+ repo, subfolder=variant, trust_remote_code=True,
93
+ mp_model_path="/path/to/face_landmarker.task"
94
+ )
95
+ # or: export EDGEFACE_MP_MODEL=/path/to/face_landmarker.task
96
+ ```
97
+
98
+ ## Batch usage
99
+
100
+ ```python
101
+ imgs = [Image.open(p).convert("RGB") for p in paths]
102
+ inputs = processor(imgs, return_tensors="pt")
103
+ with torch.no_grad():
104
+ embs = F.normalize(model(**inputs).embeddings, dim=-1) # (N, 512)
105
+ ```
106
+
107
+ ## Local import without `trust_remote_code`
108
+
109
+ Clone the source repo and import the package directly:
110
+
111
+ ```python
112
+ from edgeface import register_edgeface
113
+ register_edgeface() # wires EdgeFace into AutoConfig / AutoModel / AutoImageProcessor
114
+
115
+ model = AutoModel.from_pretrained("anjith2006/edgeface", subfolder="edgeface-xxs").eval()
116
+ processor = AutoImageProcessor.from_pretrained("anjith2006/edgeface", subfolder="edgeface-xxs")
117
+ ```
118
+
119
+ ## LoRA fine-tuning
120
+
121
+ The static low-rank layers in the gamma variants are plain `nn.Linear` modules, so PEFT targets them without any naming collision:
122
+
123
+ ```python
124
+ from peft import LoraConfig, get_peft_model
125
+
126
+ model = AutoModel.from_pretrained(repo, subfolder=variant, trust_remote_code=True)
127
+
128
+ # Gamma variants (edgeface-s-gamma-05, edgeface-xs-gamma-06):
129
+ lora_cfg = LoraConfig(r=8, lora_alpha=16, target_modules=["linear1", "linear2"])
130
+
131
+ # Base / XXS variants (no factorized layers β€” target the backbone linears directly):
132
+ # print([n for n, _ in model.named_modules() if isinstance(_, torch.nn.Linear)])
133
+ lora_cfg = LoraConfig(r=8, lora_alpha=16, target_modules=["fc1", "fc2"])
134
+
135
+ model = get_peft_model(model, lora_cfg)
136
+ model.print_trainable_parameters()
137
+ ```
138
+
139
+ ## Building the checkpoints
140
+
141
+ The weights come from the original Idiap `.pt` files. `convert_edgeface.py` downloads them, converts to `config.json` + `model.safetensors`, and pushes everything into this single repo.
142
+
143
+ ```bash
144
+ huggingface-cli login
145
+
146
+ # Convert all four variants and push to anjith2006/edgeface
147
+ python convert_edgeface.py --push anjith2006
148
+
149
+ # Convert one variant locally only (no push)
150
+ python convert_edgeface.py --only edgeface_xxs
151
+ ```
152
+
153
+ ### Verify after converting
154
+
155
+ ```bash
156
+ python example.py ./edgeface-xxs same1.jpg same2.jpg different.jpg
157
+ # cos(A, B) = 0.9xxx
158
+ # cos(A, C) = 0.xxxx (expected lower)
159
+ ```
160
+
161
+ ## Source files
162
+
163
+ | File | Purpose |
164
+ |---|---|
165
+ | `configuration_edgeface.py` | `EdgeFaceConfig` |
166
+ | `modeling_edgeface.py` | `EdgeFaceModel`, `LowRankLinear`, `EdgeFaceOutput` |
167
+ | `image_processing_edgeface.py` | `EdgeFaceImageProcessor` (MediaPipe alignment + normalize) |
168
+ | `convert_edgeface.py` | Download original `.pt` checkpoints, convert, push |
169
+ | `example.py` | Same-person / different-person sanity check |
170
+
171
+ ## License
172
+
173
+ The pretrained weights and original alignment code are Β© Idiap Research Institute. The original [EdgeFace license](https://gitlab.idiap.ch/bob/bob.paper.tbiom2023_edgeface/-/blob/master/LICENSE) governs all weight files and derivative uses. See `NOTICE` for details. Verify compliance before commercial use or redistribution.
174
+
175
+ ## Citation
176
+
177
+ ```bibtex
178
+ @article{george2024edgeface,
179
+ title = {EdgeFace: Efficient Face Recognition Model for Edge Devices},
180
+ author = {George, Anjith and Ecabert, Christophe and Otroshi Shahreza, Hatef
181
+ and Kotwal, Ketan and Marcel, Sebastien},
182
+ journal = {IEEE Transactions on Biometrics, Behavior, and Identity Science},
183
+ year = {2024},
184
+ doi = {10.1109/TBIOM.2024.3352169}
185
+ }
186
+ ```