|
1 | 1 | # ICP face recognition |
2 | 2 |
|
3 | | -This is an ICP smart contract runs face detection and face recognition of user's photo that can be uploaded either from a camera or a local file. |
| 3 | +This example demonstrates running face detection and face recognition inside an ICP canister using the [Tract ONNX inference engine](https://github.com/sonos/tract). Users can upload photos from a camera or local file, detect faces, and identify people by name. |
4 | 4 |
|
5 | | -The smart contract consists of two canisters: |
| 5 | +The example consists of two canisters: |
6 | 6 |
|
7 | | -- The backend canister embeds the [the Tract ONNX inference engine](https://github.com/sonos/tract) with two ONNX models. One model is used to detect a face in the photo and return its bounding box. Another model is used for computing face embeddings. |
8 | | -- The frontend canister contains the Web assets such as HTML, JS, CSS that are served to the browser. |
| 7 | +- **backend** — embeds the Tract ONNX inference engine. Exposes endpoints for uploading ONNX model files in chunks, loading them into memory, detecting faces, computing face embeddings, and recognizing people. Also includes `run_detection` (query) and `run_recognition` (update) endpoints that run the models against a built-in test image — useful during development for capacity planning. Since query calls don't persist logs on ICP, only the update call produces a visible instruction count: |
9 | 8 |
|
10 | | -# Models |
| 9 | + ```bash |
| 10 | + icp canister call backend run_recognition '()' |
| 11 | + icp canister logs backend |
| 12 | + ``` |
| 13 | +- **frontend** — serves the web UI (HTML/JS/CSS). |
11 | 14 |
|
12 | | -The smart contract uses two models: one for detecting the face and another for recognizing the face. |
| 15 | +## Models |
13 | 16 |
|
14 | | -## Face detection |
| 17 | +The backend uses two ONNX models that are too large to embed in the Wasm binary and must be uploaded after deployment. `icp deploy` handles this automatically via its sync phase: |
15 | 18 |
|
16 | | -A face detection model finds the bounding box of a face in the image. |
17 | | -You can download [Ultraface](https://github.com/onnx/models/tree/main/validated/vision/body_analysis/ultraface) - ultra-lightweight face detection model - [[here](https://github.com/onnx/models/blob/bec48b6a70e5e9042c0badbaafefe4454e072d08/validated/vision/body_analysis/ultraface/models/version-RFB-320.onnx)]. |
| 19 | +- **Face detection** ([Ultraface](https://github.com/onnx/models/tree/main/validated/vision/body_analysis/ultraface)) — downloaded automatically. |
| 20 | +- **Face recognition** ([facenet-pytorch](https://github.com/timesler/facenet-pytorch) InceptionResnetV1) — generated automatically if Python 3.9–3.12 is available (`facenet-pytorch`, `torch`, and `onnx` are installed via pip). If no compatible Python is found, place `face-recognition.onnx` in the project root manually and run `icp deploy` again. |
18 | 21 |
|
19 | | -Alternatively, you can run |
| 22 | +Models are stored in stable memory and survive canister upgrades — they reload automatically without re-uploading. Note: the persons database (added via the frontend) is stored in heap memory and is cleared on upgrade. |
20 | 23 |
|
21 | | -``` |
22 | | -./download-face-detection-model.sh |
23 | | -``` |
24 | | - |
25 | | -## Face recognition |
26 | | - |
27 | | -A face recognition model computes a vector embedding of an image with a face. |
28 | | -You can obtain a pretrained model from [facenet-pytorch](https://github.com/timesler/facenet-pytorch) as follows. |
| 24 | +## Build and deploy from the command line |
29 | 25 |
|
30 | | -- #### Step 1: Install `python` and `pip`: https://packaging.python.org/en/latest/tutorials/installing-packages/. |
| 26 | +### Prerequisites |
31 | 27 |
|
32 | | -- #### Step 2: Install `facenet-pytorch` and `torch`: |
| 28 | +**Required:** |
33 | 29 |
|
34 | | -``` |
35 | | -pip install facenet-pytorch |
36 | | -pip install torch |
37 | | -pip install onnx |
38 | | -``` |
| 30 | +- [Node.js](https://nodejs.org/) v18+ |
| 31 | +- [icp-cli](https://cli.internetcomputer.org/): `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm` |
| 32 | +- [Rust](https://www.rust-lang.org/tools/install) v1.85+ with `wasm32-wasip1` target: `rustup target add wasm32-wasip1` |
| 33 | +- [wasi2ic](https://github.com/wasm-forge/wasi2ic): `cargo install wasi2ic` |
39 | 34 |
|
40 | | -- #### Step 3: Export ONNX model. Start a python shell and run the following commands or create a python file and run it: |
| 35 | +`wasm-opt` is installed automatically on first deploy if not already present. |
41 | 36 |
|
42 | | -``` |
43 | | -import torch |
44 | | -import facenet_pytorch |
45 | | -resnet = facenet_pytorch.InceptionResnetV1(pretrained='vggface2').eval() |
46 | | -input = torch.randn(1, 3, 160, 160) |
47 | | -torch.onnx.export(resnet, input, "face-recognition.onnx", verbose=False, opset_version=11) |
48 | | -``` |
| 37 | +**Optional (for automatic face recognition model generation):** |
49 | 38 |
|
50 | | -- #### Step 4: This should produce `face-recognition.onnx`. Copy the file to the root of this repository. |
| 39 | +- Python 3.9–3.12 with pip — the sync phase auto-installs `facenet-pytorch`, `torch`, and `onnx` and generates `face-recognition.onnx`. Python 3.13+ is not yet supported by torch. |
51 | 40 |
|
52 | | -## Prerequisites |
| 41 | +### Install |
53 | 42 |
|
54 | | -- [x] Install the [IC |
55 | | - SDK](https://internetcomputer.org/docs/current/developer-docs/getting-started/install). For local testing, `dfx >= 0.22.0` is required. |
56 | | -- [x] Clone the example dapp project: `git clone https://github.com/dfinity/examples` |
57 | | -- [x] Install `wasi2ic`: Follow the steps in https://github.com/wasm-forge/wasi2ic and make sure that `wasi2ic` binary is in your `$PATH`. |
58 | | -- [x] Install `wasm-opt`: `cargo install wasm-opt` |
| 43 | +```bash |
| 44 | +git clone https://github.com/dfinity/examples |
| 45 | +cd examples/rust/face-recognition |
| 46 | +``` |
59 | 47 |
|
60 | | -## Build the application |
| 48 | +### Deploy |
61 | 49 |
|
62 | | -``` |
63 | | -dfx start --background |
64 | | -dfx deploy |
| 50 | +```bash |
| 51 | +icp network start -d |
| 52 | +icp deploy |
| 53 | +icp network stop |
65 | 54 | ``` |
66 | 55 |
|
67 | | -If the deployment is successful, the it will show the `frontend` URL. |
68 | | -Open that URL in browser to interact with the smart contract. |
| 56 | +`icp deploy` runs three phases: |
| 57 | +1. **Build** — compiles the Rust backend to WASM (via wasm32-wasip1 + wasi2ic). |
| 58 | +2. **Deploy** — installs the backend and frontend canisters. |
| 59 | +3. **Sync** — downloads the face detection model, generates the face recognition model (if Python 3.9–3.12 is available), and uploads both to the canister. Skipped on redeployment if models are already loaded. |
69 | 60 |
|
70 | | -## Chunk uploading of models |
| 61 | +After deployment the CLI prints the frontend URL. Open it in a browser to interact with the canister. |
71 | 62 |
|
72 | | -Since the models are large, they cannot be embedded into the Wasm binary of the smart contract. |
73 | | -Instead they should be uploaded separately. |
| 63 | +### Test |
74 | 64 |
|
75 | | -[DecideAI](https://decideai.xyz/) implemented a tool for incremental uploading of models: https://github.com/modclub-app/ic-file-uploader/tree/main. |
| 65 | +```bash |
| 66 | +bash test.sh |
| 67 | +``` |
76 | 68 |
|
77 | | -You can install the tool with |
| 69 | +`test.sh` exercises the model management API without requiring models to be loaded. The frontend shows a setup instruction if models are not yet uploaded. |
78 | 70 |
|
79 | | -``` |
80 | | -cargo install ic-file-uploader |
| 71 | +For frontend development with hot reload: |
| 72 | + |
| 73 | +```bash |
| 74 | +npm run dev --prefix frontend |
81 | 75 | ``` |
82 | 76 |
|
83 | | -Afterwards, execute the `upload-models-to-canister.sh` script, which runs the following commands: |
| 77 | +## Updating the Candid interface |
84 | 78 |
|
85 | | -``` |
86 | | -dfx canister call backend clear_face_detection_model_bytes |
87 | | -dfx canister call backend clear_face_recognition_model_bytes |
88 | | -ic-file-uploader backend append_face_detection_model_bytes version-RFB-320.onnx |
89 | | -ic-file-uploader backend append_face_recognition_model_bytes face-recognition.onnx |
90 | | -dfx canister call backend setup_models |
| 79 | +Only needed if you change the backend endpoints. Requires `candid-extractor` (`cargo install candid-extractor`): |
| 80 | + |
| 81 | +```bash |
| 82 | +icp build backend && candid-extractor ./target/wasm32-wasip1/release/backend.wasm > backend/backend.did |
91 | 83 | ``` |
92 | 84 |
|
93 | 85 | ## Credits |
94 | 86 |
|
95 | | -Thanks to [DecideAI](https://decideai.xyz/) for discussions and providing [ic-file-uploader](https://github.com/modclub-app/ic-file-uploader/tree/main). |
| 87 | +Thanks to [DecideAI](https://decideai.xyz/) for discussions and providing [ic-file-uploader](https://github.com/decide-ai/ic-file-uploader). |
| 88 | + |
| 89 | +## Security considerations and best practices |
96 | 90 |
|
| 91 | +See the [ICP security best practices](https://docs.internetcomputer.org/guides/security/overview). |
0 commit comments