Skip to content

Commit 44c8ad1

Browse files
authored
Added InstantID example (#85)
* added InstantID example * use volume
1 parent f7a2575 commit 44c8ad1

4 files changed

Lines changed: 249 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Beam SDK
2+
.beamignore
3+
pyproject.toml
4+
.git
5+
.idea
6+
.python-version
7+
.vscode
8+
.venv
9+
venv
10+
__pycache__
11+
.DS_Store
12+
.config
13+
drive/MyDrive
14+
.coverage
15+
.pytest_cache
16+
.ipynb
17+
.ruff_cache
18+
.dockerignore
19+
.ipynb_checkpoints
20+
.env.local
21+
.envrc
22+
**/__pycache__/
23+
**/.pytest_cache/
24+
**/node_modules/
25+
**/.venv/
26+
*.pyc
27+
.next/
28+
.circleci
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# InstantID
2+
3+
## Overview
4+
5+
This repository contains the implementation of InstantID as a Beam endpoint.
6+
7+
In your shell, start by uploading the model:
8+
9+
`python upload.py`
10+
11+
After that, run `beam deploy app.py:generate_image` to deploy the model
12+
13+
To use this endpoint with curl:
14+
15+
```bash
16+
curl -X POST 'https://your-beam-endpoint.app.beam.cloud' \
17+
-H 'Connection: keep-alive' \
18+
-H 'Content-Type: application/json' \
19+
-H 'Authorization: YOUR_BEAM_API_KEY' \
20+
-d '{ "image": "https://hips.hearstapps.com/hmg-prod/images/screen-shot-2024-05-22-at-3-00-35-pm-664e410d9114a.png",
21+
"prompt": "analog film photo of a man. faded film, desaturated, 35mm photo, grainy, vignette"
22+
}'
23+
```
24+
25+
Response:
26+
27+
```json
28+
{
29+
"output_url": "https://app.beam.cloud/output/id/f43f5411-d96b-48b1-bab6-28b2defb9b36"
30+
}
31+
```
32+
33+
## Input Parameters
34+
35+
| Parameter | Description | Default Value |
36+
| --------- | ----------------------------------- | -------------------- |
37+
| `image` | Input reference image | URL to sample image |
38+
| `prompt` | Text prompt describing output style | "film noir style..." |

image_generation/instant_id/app.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
from beam import endpoint, Image, Output, Volume
2+
3+
VOLUME_PATH = "/instant-id"
4+
5+
image = (
6+
Image(python_version="python3.11")
7+
.add_commands(
8+
[
9+
"apt-get update",
10+
"apt-get install -y libgl1-mesa-glx libglib2.0-0 build-essential g++ python3-dev wget unzip",
11+
]
12+
)
13+
.add_python_packages(
14+
[
15+
"opencv-python==4.9.0.80",
16+
"transformers==4.37.0",
17+
"accelerate==0.26.1",
18+
"insightface==0.7.3",
19+
"diffusers==0.25.1",
20+
"onnxruntime==1.16.3",
21+
"omegaconf==2.3.0",
22+
"gradio==3.50.2",
23+
"peft==0.8.2",
24+
"controlnet-aux==0.0.7",
25+
"huggingface_hub==0.25.2",
26+
"gdown",
27+
]
28+
)
29+
.add_commands(
30+
[
31+
"git clone https://github.com/zsxkib/InstantID.git /instantid",
32+
]
33+
)
34+
)
35+
36+
37+
@endpoint(
38+
name="instant-id",
39+
cpu=12,
40+
memory="32Gi",
41+
gpu="A10G",
42+
image=image,
43+
volumes=[Volume(name="instant-id", mount_path=VOLUME_PATH)],
44+
)
45+
def generate_image(
46+
image: str = "https://live-production.wcms.abc-cdn.net.au/a241657894f4d79f0c3ea0705f0f1f07?impolicy=wcms_crop_resize&cropH=1989&cropW=2992&xPos=8&yPos=8&width=862&height=575",
47+
prompt: str = "film noir style, ink sketch|vector, male man, highly detailed, sharp focus, ultra sharpness, monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic",
48+
):
49+
import sys
50+
51+
sys.path.append("/instantid")
52+
from diffusers.utils import load_image
53+
from diffusers.models import ControlNetModel
54+
import cv2
55+
import torch
56+
import numpy as np
57+
from insightface.app import FaceAnalysis
58+
import requests
59+
import uuid
60+
61+
from pipeline_stable_diffusion_xl_instantid import (
62+
StableDiffusionXLInstantIDPipeline,
63+
draw_kps,
64+
)
65+
66+
app = FaceAnalysis(
67+
name="antelopev2",
68+
root=VOLUME_PATH,
69+
providers=["CUDAExecutionProvider", "CPUExecutionProvider"],
70+
)
71+
app.prepare(ctx_id=0, det_size=(640, 640))
72+
73+
face_adapter = f"{VOLUME_PATH}/checkpoints/ip-adapter.bin"
74+
controlnet_path = f"{VOLUME_PATH}/checkpoints/ControlNetModel/ControlNetModel"
75+
base_model = f"{VOLUME_PATH}/weights"
76+
77+
controlnet = ControlNetModel.from_pretrained(
78+
controlnet_path, torch_dtype=torch.float16
79+
)
80+
81+
pipe = StableDiffusionXLInstantIDPipeline.from_pretrained(
82+
base_model, controlnet=controlnet, torch_dtype=torch.float16
83+
)
84+
pipe.cuda()
85+
86+
pipe.load_ip_adapter_instantid(face_adapter)
87+
88+
response = requests.get(image)
89+
response.raise_for_status()
90+
91+
img_path = "/tmp/" + str(uuid.uuid4()) + ".png"
92+
with open(img_path, "wb") as f:
93+
f.write(response.content)
94+
95+
face_image = load_image(img_path)
96+
97+
face_info = app.get(cv2.cvtColor(np.array(face_image), cv2.COLOR_RGB2BGR))
98+
face_info = sorted(
99+
face_info,
100+
key=lambda x: (x["bbox"][2] - x["bbox"][0]) * (x["bbox"][3] - x["bbox"][1]),
101+
)[-1]
102+
face_emb = face_info["embedding"]
103+
face_kps = draw_kps(face_image, face_info["kps"])
104+
105+
image = pipe(
106+
prompt,
107+
image_embeds=face_emb,
108+
image=face_kps,
109+
controlnet_conditioning_scale=0.8,
110+
ip_adapter_scale=0.8,
111+
).images[0]
112+
113+
output_path = "/tmp/" + str(uuid.uuid4()) + ".png"
114+
image.save(output_path)
115+
output = Output(path=output_path)
116+
output.save()
117+
output_url = output.public_url()
118+
119+
return {"output_url": output_url}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from beam import function, Volume, Image
2+
3+
VOLUME_PATH = "./instant-id"
4+
5+
6+
@function(
7+
image=Image()
8+
.add_python_packages(
9+
["huggingface_hub", "datasets", "huggingface_hub[hf-transfer]", "gdown"]
10+
)
11+
.add_commands(
12+
[
13+
"apt-get update",
14+
"apt-get install -y unzip",
15+
]
16+
)
17+
.with_envs("HF_HUB_ENABLE_HF_TRANSFER=1"),
18+
memory="32Gi",
19+
cpu=4,
20+
secrets=["HF_TOKEN"],
21+
volumes=[Volume(name="instant-id", mount_path=VOLUME_PATH)],
22+
)
23+
def upload():
24+
from huggingface_hub import hf_hub_download, snapshot_download
25+
import gdown
26+
import os
27+
28+
snapshot_download(
29+
repo_id="wangqixun/YamerMIX_v8",
30+
local_dir=f"{VOLUME_PATH}/weights",
31+
)
32+
33+
controlnet_dir = f"{VOLUME_PATH}/checkpoints/ControlNetModel"
34+
os.makedirs(controlnet_dir, exist_ok=True)
35+
36+
hf_hub_download(
37+
repo_id="InstantX/InstantID",
38+
filename="ControlNetModel/config.json",
39+
local_dir=controlnet_dir,
40+
)
41+
hf_hub_download(
42+
repo_id="InstantX/InstantID",
43+
filename="ControlNetModel/diffusion_pytorch_model.safetensors",
44+
local_dir=controlnet_dir,
45+
)
46+
47+
hf_hub_download(
48+
repo_id="InstantX/InstantID",
49+
filename="ip-adapter.bin",
50+
local_dir=f"{VOLUME_PATH}/checkpoints",
51+
)
52+
53+
os.makedirs(f"{VOLUME_PATH}/models", exist_ok=True)
54+
gdown.download(
55+
url="https://drive.google.com/uc?id=18wEUfMNohBJ4K3Ly5wpTejPfDzp-8fI8",
56+
output=f"{VOLUME_PATH}/models/antelopev2.zip",
57+
quiet=False,
58+
fuzzy=True,
59+
)
60+
os.system(f"unzip {VOLUME_PATH}/models/antelopev2.zip -d {VOLUME_PATH}/models/")
61+
62+
63+
if __name__ == "__main__":
64+
upload()

0 commit comments

Comments
 (0)