Spaces:
Sleeping
Sleeping
File size: 3,948 Bytes
e81f668 9a7f5c2 e81f668 9a7f5c2 e81f668 9a7f5c2 e81f668 9a7f5c2 e81f668 9a7f5c2 e81f668 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
'''
python seg_script.py Genshin_Impact_Images Genshin_Impact_Images_Seg
'''
import os
import cv2
import argparse
from PIL import Image
import numpy as np
from tqdm import tqdm
from pathlib import Path
from animeinsseg import AnimeInsSeg, AnimeInstances
from animeinsseg.anime_instances import get_color
# 设置模型路径
ckpt = r'models/AnimeInstanceSegmentation/rtmdetl_e60.ckpt'
mask_thres = 0.3
instance_thres = 0.3
refine_kwargs = {'refine_method': 'refinenet_isnet'} # 如果不使用 refinenet,设置为 None
# refine_kwargs = None
# 初始化模型
net = AnimeInsSeg(ckpt, mask_thr=mask_thres, refine_kwargs=refine_kwargs)
def process_image(image_path, output_dir):
# 读取图像
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 推理
instances: AnimeInstances = net.infer(
img,
output_type='numpy',
pred_score_thr=instance_thres
)
# 初始化输出图像
drawed = img.copy()
im_h, im_w = img.shape[:2]
# 创建黑色背景的 mask 图像
mask_image = np.zeros((im_h, im_w), dtype=np.uint8)
# 如果没有检测到对象,直接返回原图
if instances.bboxes is None:
return
# 处理每个实例
for ii, (xywh, mask) in enumerate(zip(instances.bboxes, instances.masks)):
color = get_color(ii)
mask_alpha = 0.5
linewidth = max(round(sum(img.shape) / 2 * 0.003), 2)
# 绘制边界框
p1, p2 = (int(xywh[0]), int(xywh[1])), (int(xywh[2] + xywh[0]), int(xywh[3] + xywh[1]))
cv2.rectangle(drawed, p1, p2, color, thickness=linewidth, lineType=cv2.LINE_AA)
# 绘制掩码
p = mask.astype(np.float32)
blend_mask = np.full((im_h, im_w, 3), color, dtype=np.float32)
alpha_msk = (mask_alpha * p)[..., None]
alpha_ori = 1 - alpha_msk
drawed = drawed * alpha_ori + alpha_msk * blend_mask
drawed = drawed.astype(np.uint8)
# 将当前实例的 mask 绘制到黑色背景上(白色表示 mask)
mask_image[mask > 0] = 255
# 裁剪图像
x1, y1, x2, y2 = int(xywh[0]), int(xywh[1]), int(xywh[0] + xywh[2]), int(xywh[1] + xywh[3])
cropped_img = img[y1:y2, x1:x2]
cropped_mask = mask[y1:y2, x1:x2]
# 创建透明通道的边缘图
alpha_channel = (cropped_mask * 255).astype(np.uint8)
rgba_image = np.dstack((cropped_img, alpha_channel))
# 保存裁剪后的图像和分割后的图像
base_name = Path(image_path).stem
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
# 保存裁剪后的图像
Image.fromarray(cropped_img).save(output_path / f"{base_name}_cropped_{ii}.png")
# 保存分割后的图像(RGBA)
Image.fromarray(rgba_image, 'RGBA').save(output_path / f"{base_name}_segmented_{ii}.png")
# 保存绘制后的图像
Image.fromarray(drawed).save(output_path / f"{base_name}_drawed.png")
# 保存 mask 图像
Image.fromarray(mask_image).save(output_path / f"{base_name}_mask.png")
def main():
parser = argparse.ArgumentParser(description="Anime Instance Segmentation")
parser.add_argument("input_path", type=str, help="Path to the input image or folder")
parser.add_argument("output_dir", type=str, help="Path to the output directory")
args = parser.parse_args()
input_path = Path(args.input_path)
output_dir = Path(args.output_dir)
if input_path.is_file():
process_image(input_path, output_dir)
elif input_path.is_dir():
image_paths = list(input_path.rglob("*.png")) + list(input_path.rglob("*.jpg"))
for image_path in tqdm(image_paths, desc="Processing images"):
process_image(image_path, output_dir)
else:
print("Invalid input path. Please provide a valid image or folder path.")
if __name__ == "__main__":
main() |