Instructions to use Banaxi-Tech/face-model with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- ultralytics
How to use Banaxi-Tech/face-model with ultralytics:
from huggingface_hub import hf_hub_download from ultralytics import YOLO # pick the weights file from this repo's "Files and versions" tab weights = hf_hub_download("Banaxi-Tech/face-model", "<weights>.pt") model = YOLO(weights) source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True) - Notebooks
- Google Colab
- Kaggle
Download code/quantize_int8.py from Banaxi-Tech/face-model: direct link, hf CLI and curl.
- Browser
- Download file 2.76 kB
-
https://huggingface.co/Banaxi-Tech/face-model/resolve/main/code/quantize_int8.py
- Command line
-
hf download hf://Banaxi-Tech/face-model/code/quantize_int8.py
-
curl -L -o quantize_int8.py https://huggingface.co/Banaxi-Tech/face-model/resolve/main/code/quantize_int8.py
2.76 kB
| #!/usr/bin/env python3 | |
| """Post-training static INT8 quantization (QDQ, per-channel weights) of the face detector ONNX. | |
| Usage: python quantize_int8.py export/face_yolo11n_fp32.onnx export/face_yolo11n_int8.onnx [--calib 300] | |
| """ | |
| import argparse | |
| import random | |
| from pathlib import Path | |
| import cv2 | |
| import numpy as np | |
| import onnx | |
| from onnxruntime.quantization import CalibrationDataReader, CalibrationMethod, QuantFormat, QuantType, quantize_static | |
| def letterbox(img, size=640): | |
| h, w = img.shape[:2] | |
| s = min(size / h, size / w) | |
| nh, nw = round(h * s), round(w * s) | |
| img = cv2.resize(img, (nw, nh), interpolation=cv2.INTER_LINEAR) | |
| canvas = np.full((size, size, 3), 114, np.uint8) | |
| top, left = (size - nh) // 2, (size - nw) // 2 | |
| canvas[top:top + nh, left:left + nw] = img | |
| return canvas | |
| class Reader(CalibrationDataReader): | |
| def __init__(self, files, input_name): | |
| self.it = iter(files) | |
| self.name = input_name | |
| def get_next(self): | |
| f = next(self.it, None) | |
| if f is None: | |
| return None | |
| img = letterbox(cv2.imread(str(f)))[:, :, ::-1].transpose(2, 0, 1) # BGR->RGB, CHW | |
| return {self.name: (img[None].astype(np.float32) / 255.0)} | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("src") | |
| ap.add_argument("dst") | |
| ap.add_argument("--calib", type=int, default=300) | |
| ap.add_argument("--images", default="dataset/images/train") | |
| a = ap.parse_args() | |
| random.seed(0) | |
| files = sorted(Path(a.images).glob("*.jpg")) | |
| random.shuffle(files) | |
| files = files[:a.calib] | |
| g = onnx.load(a.src).graph | |
| inp = g.input[0].name | |
| # The Detect head's decode (DFL box decoding, class Sigmoid, final Concats) mixes box values up to 640 with | |
| # 0-1 class scores in one tensor; INT8 would give them one shared scale and crush the scores. Keep it float. | |
| exclude = [n.name for n in g.node | |
| if n.name.startswith("/model.23/") and not n.name.startswith(("/model.23/cv2.", "/model.23/cv3."))] | |
| print(f"keeping {len(exclude)} decode nodes in float") | |
| quantize_static(a.src, a.dst, Reader(files, inp), quant_format=QuantFormat.QDQ, per_channel=True, | |
| weight_type=QuantType.QInt8, activation_type=QuantType.QUInt8, | |
| calibrate_method=CalibrationMethod.MinMax, nodes_to_exclude=exclude) | |
| # keep ultralytics metadata (class names, stride, imgsz) so the model loads like the original | |
| src, q = onnx.load(a.src), onnx.load(a.dst) | |
| del q.metadata_props[:] | |
| q.metadata_props.extend(src.metadata_props) | |
| onnx.save(q, a.dst) | |
| print(f"RES wrote {a.dst}: {Path(a.dst).stat().st_size / 1e6:.1f} MB (from {Path(a.src).stat().st_size / 1e6:.1f} MB)") | |
| if __name__ == "__main__": | |
| main() | |