Skip to content

Commit 8dd1785

Browse files
committed
refine the sam nodes
1 parent 2bd83d9 commit 8dd1785

2 files changed

Lines changed: 349 additions & 0 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
name: workflows-ci
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
environment:
7+
description: 'The environment to deploy the workflow to'
8+
required: true
9+
default: 'uat'
10+
branch:
11+
description: 'The branch to checkout code from'
12+
required: true
13+
default: 'master'
14+
pull_request:
15+
branches:
16+
- master
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.inputs.environment }}
20+
cancel-in-progress: true
21+
22+
env:
23+
test_script: test_sam.py
24+
target_branch: ${{ github.base_ref || 'master' }}
25+
26+
jobs:
27+
check-modified-files:
28+
runs-on: ubuntu-latest
29+
outputs:
30+
only_non_code_files: ${{ steps.check_files.outputs.only_non_code_files }}
31+
steps:
32+
- name: Checkout repository
33+
uses: actions/checkout@v4
34+
with:
35+
fetch-depth: 0
36+
ref: ${{ github.head_ref || github.event.inputs.branch }}
37+
38+
- name: Fetch target branch
39+
run: |
40+
git fetch origin ${{ env.target_branch }} --depth=1
41+
42+
- name: Check modified files
43+
id: check_files
44+
run: |
45+
modified_files=$(git diff --name-only origin/${{ env.target_branch }}...HEAD)
46+
only_non_code_files=true
47+
for file in $modified_files; do
48+
if [[ "$file" == *.py ]] || [[ "$file" == *.js ]] || [[ "$file" == *.json ]] || [[ "$file" == *.yml ]]; then
49+
only_non_code_files=false
50+
break
51+
fi
52+
done
53+
echo "only_non_code_files=$only_non_code_files" >> $GITHUB_OUTPUT
54+
55+
- name: Debug only_non_code_files
56+
run: echo "only_non_code_files=${{ steps.check_files.outputs.only_non_code_files }}"
57+
58+
run-examples-workflows:
59+
needs: check-modified-files
60+
if: ${{ needs.check-modified-files.outputs.only_non_code_files == 'false' }} || ${{ github.event_name == 'workflow_dispatch' }}
61+
runs-on: ${{ matrix.os }}
62+
strategy:
63+
matrix:
64+
os: [windows-latest, ubuntu-latest]
65+
environment: ${{ github.event.inputs.environment || 'prod' }}
66+
67+
steps:
68+
- name: Show Base
69+
run: |
70+
echo "Current directory: $(pwd)"
71+
72+
- name: Checkout ComfyUI
73+
uses: actions/checkout@v4
74+
with:
75+
repository: comfyanonymous/ComfyUI
76+
path: ComfyUI
77+
ref: v0.3.7
78+
79+
- name: Checkout plugin repository
80+
uses: actions/checkout@v4
81+
with:
82+
path: ComfyUI/custom_nodes/BizyAir
83+
84+
- name: Set up Python
85+
uses: actions/setup-python@v5
86+
with:
87+
python-version: '3.10'
88+
89+
- name: Cache pip packages
90+
uses: actions/cache@v4
91+
with:
92+
path: ~/.cache/pip
93+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
94+
restore-keys: |
95+
${{ runner.os }}-pip-
96+
97+
- name: Install dependencies
98+
run: |
99+
python3 -m pip install --upgrade pip
100+
python3 -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
101+
python3 -m pip install -r ComfyUI/requirements.txt
102+
python3 -m pip install -r ComfyUI/custom_nodes/BizyAir/requirements.txt
103+
python3 -m pip show torch
104+
105+
- name: Run ComfyUI on Linux
106+
if: matrix.os == 'ubuntu-latest'
107+
run: |
108+
cd ComfyUI
109+
nohup python main.py --port 8188 --cpu > >(tee -a service.log) 2>&1 &
110+
111+
cd custom_nodes/BizyAir
112+
echo "Current directory: $(pwd)"
113+
python3 tests/write_api_ini_file.py
114+
python3 tests/${{ env.test_script }}
115+
env:
116+
BIZYAIR_KEY: ${{ secrets.BIZYAIR_KEY }}
117+
BIZYAIR_API_KEY: ${{ secrets.BIZYAIR_KEY }}
118+
BIZYAIR_SERVER_ADDRESS: ${{ vars.BIZYAIR_SERVER_ADDRESS }}
119+
PYTHONPATH: ${{ github.workspace }}/ComfyUI
120+
BIZYAIR_TEST_SKIP_WORKFLOW_IDS: ${{ vars.BIZYAIR_TEST_SKIP_WORKFLOW_IDS }}
121+
BIZYAIR_OFFICIAL_WORKFLOW_MAX_TOTAL: ${{ vars.BIZYAIR_OFFICIAL_WORKFLOW_MAX_TOTAL }}
122+
123+
- name: Run ComfyUI on Windows
124+
if: matrix.os == 'windows-latest'
125+
run: |
126+
cd ComfyUI
127+
Start-Process -FilePath "python3" -ArgumentList "main.py --port 8188 --cpu" -NoNewWindow
128+
cd custom_nodes/BizyAir
129+
Write-Output "Current directory: $(Get-Location)"
130+
python3 tests/write_api_ini_file.py
131+
python3 tests/${{ env.test_script }}
132+
env:
133+
BIZYAIR_KEY: ${{ secrets.BIZYAIR_KEY }}
134+
BIZYAIR_API_KEY: ${{ secrets.BIZYAIR_KEY }}
135+
BIZYAIR_SERVER_ADDRESS: ${{ vars.BIZYAIR_SERVER_ADDRESS }}
136+
PYTHONPATH: ${{ github.workspace }}/ComfyUI
137+
PYTHONIOENCODING: utf-8
138+
BIZYAIR_TEST_SKIP_WORKFLOW_IDS: ${{ vars.BIZYAIR_TEST_SKIP_WORKFLOW_IDS }}
139+
BIZYAIR_OFFICIAL_WORKFLOW_MAX_TOTAL: ${{ vars.BIZYAIR_OFFICIAL_WORKFLOW_MAX_TOTAL }}

tests/test_sam.py

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import base64
2+
import io
3+
import json
4+
import os
5+
import sys
6+
from io import BytesIO
7+
8+
import imageio.v2 as imageio
9+
import numpy as np
10+
import requests
11+
import torch
12+
from PIL import Image
13+
14+
# current_dir = os.path.dirname(os.path.abspath(__file__))
15+
# full_path = os.path.abspath(os.path.join(current_dir, "../../.."))
16+
# sys.path.append(full_path)
17+
18+
19+
def convert_image_to_rgb(image: Image.Image) -> Image.Image:
20+
if image.mode != "RGB":
21+
return image.convert("RGB")
22+
return image
23+
24+
25+
def encode_image_to_base64(
26+
image: Image.Image, format: str = "WEBP", quality: int = 100, **kwargs
27+
) -> str:
28+
image = convert_image_to_rgb(image)
29+
with io.BytesIO() as output:
30+
imageio.imwrite(output, image, format=format, quality=quality)
31+
output.seek(0)
32+
img_bytes = output.getvalue()
33+
return base64.b64encode(img_bytes).decode("utf-8")
34+
35+
36+
def send_request(create_task_url, payload):
37+
with TaskClient(create_task_url) as client:
38+
response = client.pull(payload)
39+
40+
if response is None:
41+
raise RuntimeError()
42+
ret = response.json()
43+
44+
if "result" in ret:
45+
msg = json.loads(ret["result"])
46+
else:
47+
msg = ret
48+
# print("why msg: ", msg)
49+
msg = msg["data"]
50+
if msg["type"] not in (
51+
"comfyair",
52+
"bizyair",
53+
):
54+
raise Exception(f"Unexpected response type: {msg}")
55+
56+
if "error" in msg:
57+
raise Exception(f"Error happens: {msg}")
58+
59+
# img = msg["image"]
60+
# mask_img = msg["mask_image"]
61+
62+
# output_file1 = "sam_test.webp"
63+
# output_file2 = "sam_test_mask.webp"
64+
# decode_base64_to_image(img, "webp").save(output_file1)
65+
# decode_base64_to_image(mask_img, "webp").save(output_file2)
66+
67+
68+
class TaskClient:
69+
def __init__(self, create_task_url):
70+
self.create_task_url = create_task_url
71+
72+
def __enter__(self):
73+
return self
74+
75+
def __exit__(self, exc_type, exc_value, traceback):
76+
pass
77+
78+
def pull(self, payload):
79+
response = requests.post(
80+
self.create_task_url,
81+
json=payload,
82+
headers={"Content-Type": "application/json"},
83+
)
84+
return response
85+
86+
87+
def test_task_creation_and_result_retrieval():
88+
create_task_url = "http://0.0.0.0:9899/supernode/sam"
89+
# create_task_url = "https://bizyair-api.siliconflow.cn/x/v1/supernode/sam"
90+
image_url = (
91+
"https://bizy-air.oss-cn-beijing.aliyuncs.com/examples_asset/sam-people.png"
92+
)
93+
94+
# image_to_sam = "people.png"
95+
# img_pil = Image.open(image_to_sam)
96+
97+
response = requests.get(image_url)
98+
if response.status_code == 200:
99+
img_pil = Image.open(BytesIO(response.content))
100+
else:
101+
raise Exception(
102+
f"Failed to retrieve the image, status code: {response.status_code}"
103+
)
104+
105+
mode = 2 # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
106+
107+
######################使用Point作为Prompt##############################
108+
input_points = np.array([[500, 375]])
109+
input_points = json.dumps(input_points.tolist())
110+
input_label = np.array([1])
111+
input_label = json.dumps(input_label.tolist())
112+
payload = {
113+
"image": encode_image_to_base64(img_pil),
114+
"mode": mode, # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
115+
"params": {
116+
"input_points": input_points,
117+
"input_label": input_label,
118+
"input_boxes": None,
119+
},
120+
}
121+
122+
send_request(create_task_url, payload)
123+
124+
# ###################使用Box作为Prompt##############################
125+
input_boxes = np.array([451.8652, 71.6301, 648.0280, 1022.0955])
126+
input_boxes = json.dumps(input_boxes.tolist())
127+
payload = {
128+
"image": encode_image_to_base64(img_pil),
129+
"mode": mode, # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
130+
"params": {
131+
"input_points": None,
132+
"input_label": None,
133+
"input_boxes": input_boxes,
134+
},
135+
}
136+
137+
send_request(create_task_url, payload)
138+
139+
# ######################使用Points和Box作为Prompt##############################
140+
input_boxes = np.array([451.8652, 71.6301, 648.0280, 1022.0955])
141+
input_boxes = json.dumps(input_boxes.tolist())
142+
143+
input_points = np.array([[575, 750]])
144+
input_points = json.dumps(input_points.tolist())
145+
input_label = np.array([0])
146+
input_label = json.dumps(input_label.tolist())
147+
payload = {
148+
"image": encode_image_to_base64(img_pil),
149+
"mode": mode, # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
150+
"params": {
151+
"input_points": input_points,
152+
"input_label": input_label,
153+
"input_boxes": input_boxes,
154+
},
155+
}
156+
157+
send_request(create_task_url, payload)
158+
159+
# #####################使用Batched Box作为Prompt##############################
160+
input_boxes = torch.tensor(
161+
[
162+
[24.0652, 127.0906, 181.5945, 932.2192],
163+
[451.8652, 71.6301, 648.0280, 1022.0955],
164+
[731.7250, 201.1820, 956.5409, 1022.2478],
165+
[236.7201, 131.5688, 414.6645, 979.8284],
166+
[145.1680, 183.1925, 308.3481, 955.5884],
167+
[358.4024, 192.8287, 506.4283, 1011.5869],
168+
[588.2826, 152.5342, 798.1860, 1021.6285],
169+
]
170+
)
171+
input_boxes = json.dumps(input_boxes.tolist())
172+
mode = 3
173+
payload = {
174+
"image": encode_image_to_base64(img_pil),
175+
"mode": mode, # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
176+
"params": {
177+
"input_boxes": input_boxes,
178+
},
179+
}
180+
181+
send_request(create_task_url, payload)
182+
183+
# ####################使用自动模式作为Prompt##############################
184+
mode = 0
185+
payload = {
186+
"image": encode_image_to_base64(img_pil),
187+
"mode": mode, # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
188+
}
189+
send_request(create_task_url, payload)
190+
191+
######################使用text模式作为Prompt##############################
192+
text = "human"
193+
box_threshold = 0.3
194+
text_threshold = 0.25
195+
mode = 1
196+
payload = {
197+
"image": encode_image_to_base64(img_pil),
198+
"mode": mode, # 0: auto mode 1:text mode 2: points/boxes 3: batched boxes
199+
"params": {
200+
"prompt": text,
201+
"box_threshold": box_threshold, # 检测框置信度
202+
"text_threshold": text_threshold, # 文本置信度
203+
},
204+
}
205+
206+
send_request(create_task_url, payload)
207+
208+
209+
if __name__ == "__main__":
210+
test_task_creation_and_result_retrieval()

0 commit comments

Comments
 (0)