Merge pull request #831 from Bing-su/dev

v26.2.0
main v26.2.0
Dowon 2026-02-05 22:43:40 +09:00 committed by GitHub
commit 3a599f5d46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 105 additions and 60 deletions

View File

@ -3,6 +3,7 @@ on:
push: push:
tags: tags:
- "v*" - "v*"
workflow_dispatch:
jobs: jobs:
test: test:
@ -17,10 +18,11 @@ jobs:
needs: [test] needs: [test]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
- name: Build wheel - name: Build wheel
run: pipx run build run: uv build
- name: Publish to PyPI - name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1

View File

@ -7,7 +7,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v10
with: with:
days-before-stale: 17 days-before-stale: 17
days-before-close: 3 days-before-close: 3

View File

@ -4,7 +4,9 @@ on:
pull_request: pull_request:
paths: paths:
- "adetailer/**.py" - "adetailer/**.py"
- ".github/workflows/test.yml"
workflow_call: workflow_call:
workflow_dispatch:
schedule: schedule:
- cron: "0 0 * * 0" - cron: "0 0 * * 0"
@ -13,18 +15,21 @@ jobs:
name: Test on python ${{ matrix.python-version }} name: Test on python ${{ matrix.python-version }}
runs-on: macos-latest runs-on: macos-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
python-version: python-version:
- "3.10" - "3.10"
- "3.11" - "3.11"
- "3.12" - "3.12"
- "3.13"
- "3.14"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v5 - uses: astral-sh/setup-uv@v7
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Run tests - name: Run tests
run: uv run --all-extras pytest -v run: uv run --all-extras --with 'git+https://github.com/ultralytics/CLIP.git' pytest -v

View File

@ -5,7 +5,7 @@ exclude: ^modules/
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v6.0.0
hooks: hooks:
- id: check-added-large-files - id: check-added-large-files
args: [--maxkb=100] args: [--maxkb=100]
@ -19,13 +19,13 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
- repo: https://github.com/rbubley/mirrors-prettier - repo: https://github.com/rbubley/mirrors-prettier
rev: v3.5.3 rev: v3.8.1
hooks: hooks:
- id: prettier - id: prettier
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.9 rev: v0.15.0
hooks: hooks:
- id: ruff - id: ruff-check
args: [--fix, --exit-non-zero-on-fix] args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format - id: ruff-format

View File

@ -1,7 +1,6 @@
{ {
"recommendations": [ "recommendations": [
"ms-python.vscode-pylance", "ms-python.vscode-pylance",
"ms-python.black-formatter",
"kevinrose.vsc-python-indent", "kevinrose.vsc-python-indent",
"charliermarsh.ruff", "charliermarsh.ruff",
"shardulm94.trailing-spaces" "shardulm94.trailing-spaces"

View File

@ -1,5 +1,10 @@
# Changelog # Changelog
## 2026-02-05
- v26.2.0
- segmentation 모델의 마스크 dtype이 uint8로 변경된 것에 대응
## 2025-03-10 ## 2025-03-10
- v25.3.0 - v25.3.0
@ -121,7 +126,6 @@
- YOLO World 모델 추가: 가장 큰 yolov8x-world.pt 모델만 기본적으로 선택할 수 있게 함. - YOLO World 모델 추가: 가장 큰 yolov8x-world.pt 모델만 기본적으로 선택할 수 있게 함.
- lllyasviel/stable-diffusion-webui-forge에서 컨트롤넷을 사용가능하게 함 (PR #517) - lllyasviel/stable-diffusion-webui-forge에서 컨트롤넷을 사용가능하게 함 (PR #517)
- 기본 스크립트 목록에 soft_inpainting 추가 (https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/14208) - 기본 스크립트 목록에 soft_inpainting 추가 (https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/14208)
- 기존에 설치한 사람에게 소급적용되지는 않음 - 기존에 설치한 사람에게 소급적용되지는 않음
- 감지모델에 대한 간단한 pytest 추가함 - 감지모델에 대한 간단한 pytest 추가함
@ -348,7 +352,6 @@
- `ad_inpaint_full_res``ad_inpaint_only_masked` - `ad_inpaint_full_res``ad_inpaint_only_masked`
- `ad_inpaint_full_res_padding``ad_inpaint_only_masked_padding` - `ad_inpaint_full_res_padding``ad_inpaint_only_masked_padding`
- mediapipe face mesh 모델 추가 - mediapipe face mesh 모델 추가
- mediapipe 최소 버전 `0.10.0` - mediapipe 최소 버전 `0.10.0`
- rich traceback 제거함 - rich traceback 제거함

View File

@ -1,4 +1,4 @@
from __future__ import annotations # noqa: A005 from __future__ import annotations
import io import io
import platform import platform

View File

@ -1 +1 @@
__version__ = "25.3.0" __version__ = "26.2.0"

View File

@ -61,11 +61,12 @@ def mask_to_pil(masks: torch.Tensor, shape: tuple[int, int]) -> list[Image.Image
""" """
Parameters Parameters
---------- ----------
masks: torch.Tensor, dtype=torch.float32, shape=(N, H, W). masks: torch.Tensor, dtype=torch.float32 or torch.uint8, shape=(N, H, W).
The device can be CUDA, but `to_pil_image` takes care of that. uint8 tensor is expected to have values 0 or 1 (not 0-255).
shape: tuple[int, int] shape: tuple[int, int]
(W, H) of the original image (W, H) of the original image
""" """
masks = masks.float()
n = masks.shape[0] n = masks.shape[0]
return [to_pil_image(masks[i], mode="L").resize(shape) for i in range(n)] return [to_pil_image(masks[i], mode="L").resize(shape) for i in range(n)]

View File

@ -47,7 +47,7 @@ def install():
deps = [ deps = [
# requirements # requirements
("ultralytics", "8.3.75", None), ("ultralytics", "8.3.75", None),
("mediapipe", "0.10.13", "0.10.15"), ("mediapipe", "0.10.13", None),
("rich", "13.0.0", None), ("rich", "13.0.0", None),
] ]

View File

@ -1,26 +1,26 @@
[project] [project]
name = "adetailer" name = "adetailer"
description = "An object detection and auto-mask extension for stable diffusion webui." description = "An object detection and auto-mask extension for stable diffusion webui."
authors = [{ name = "dowon", email = "ks2515@naver.com" }]
requires-python = ">=3.9"
readme = "README.md" readme = "README.md"
requires-python = ">=3.9"
license = { text = "AGPL-3.0" } license = { text = "AGPL-3.0" }
dependencies = [ authors = [{ name = "dowon", email = "ks2515@naver.com" }]
"ultralytics>=8.2",
"mediapipe>=0.10.13",
"pydantic<3",
"rich>=13",
"huggingface_hub",
]
keywords = [ keywords = [
"stable-diffusion", "adetailer",
"stable-diffusion-webui", "stable-diffusion",
"adetailer", "stable-diffusion-webui",
"ultralytics", "ultralytics",
] ]
classifiers = [ classifiers = [
"License :: OSI Approved :: GNU Affero General Public License v3", "License :: OSI Approved :: GNU Affero General Public License v3",
"Topic :: Scientific/Engineering :: Image Recognition", "Topic :: Scientific/Engineering :: Image Recognition",
]
dependencies = [
"huggingface-hub",
"mediapipe>=0.10.13",
"pydantic<3",
"rich>=13",
"ultralytics>=8.2",
] ]
dynamic = ["version"] dynamic = ["version"]
@ -28,7 +28,7 @@ dynamic = ["version"]
repository = "https://github.com/Bing-su/adetailer" repository = "https://github.com/Bing-su/adetailer"
[project.optional-dependencies] [project.optional-dependencies]
dev = ["ruff", "pre-commit", "devtools"] dev = ["devtools"]
test = ["pytest", "hypothesis"] test = ["pytest", "hypothesis"]
[build-system] [build-system]
@ -48,32 +48,33 @@ extend-exclude = ["modules"]
[tool.ruff.lint] [tool.ruff.lint]
select = [ select = [
"A", "A",
"B", "B",
"C4", "C4",
"C90", "C90",
"E", "E",
"EM", "EM",
"F", "F",
"FA", "FA",
"I001", "I001",
"ISC", "ISC",
"N", "N",
"PD", "PD",
"PERF", "PERF",
"PL", "PL",
"PIE", "PLC",
"PT", "PIE",
"PTH", "PT",
"RET", "PTH",
"RUF", "RET",
"SIM", "RUF",
"T20", "SIM",
"TRY", "T20",
"UP", "TRY",
"W", "UP",
"W",
] ]
ignore = ["B905", "E501", "PLR2004", "PLW0603"] ignore = ["B905", "E501", "PLC0415", "PLR2004", "PLW0603"]
unfixable = ["F401"] unfixable = ["F401"]
[tool.ruff.lint.isort] [tool.ruff.lint.isort]

View File

@ -1,8 +1,10 @@
import numpy as np
import pytest import pytest
import torch
from huggingface_hub import hf_hub_download from huggingface_hub import hf_hub_download
from PIL import Image from PIL import Image
from adetailer.ultralytics import ultralytics_predict from adetailer.ultralytics import mask_to_pil, ultralytics_predict
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -60,3 +62,35 @@ def test_yolo_world(sample_image2: Image.Image, klass: str):
assert len(result.masks) > 0 assert len(result.masks) > 0
assert len(result.confidences) > 0 assert len(result.confidences) > 0
assert len(result.bboxes) == len(result.masks) == len(result.confidences) assert len(result.bboxes) == len(result.masks) == len(result.confidences)
class TestMaskToPil:
def test_mask_to_pil_float32(self):
mask = torch.tensor([[[0.0, 1.0], [0.0, 1.0]]], dtype=torch.float32)
imgs = mask_to_pil(mask, shape=(2, 2))
assert len(imgs) == 1
img = imgs[0]
assert isinstance(img, Image.Image)
arr = np.array(img)
assert arr.shape == (2, 2)
assert arr.dtype == np.uint8
expected = np.array([[0, 255], [0, 255]], dtype=np.uint8)
np.testing.assert_array_equal(arr, expected)
def test_mask_to_pil_uint8(self):
mask = torch.tensor([[[0, 1], [0, 1]]], dtype=torch.uint8)
imgs = mask_to_pil(mask, shape=(2, 2))
assert len(imgs) == 1
img = imgs[0]
assert isinstance(img, Image.Image)
arr = np.array(img)
assert arr.shape == (2, 2)
assert arr.dtype == np.uint8
expected = np.array([[0, 255], [0, 255]], dtype=np.uint8)
np.testing.assert_array_equal(arr, expected)