设置通道

This commit is contained in:
2025-12-10 19:28:34 +08:00
parent a829f035b3
commit 1d763dfc3c
3 changed files with 181 additions and 0 deletions

View File

@ -3,6 +3,7 @@ from PIL import Image, ImageFilter, ImageDraw, ImageStat
from PIL import ImageEnhance
from PIL import ImageChops
from PIL import ImageOps
import cv2
from konabot.plugins.fx_process.color_handle import ColorHandle
@ -12,6 +13,7 @@ from konabot.plugins.fx_process.gradient import GradientGenerator
import numpy as np
from konabot.plugins.fx_process.image_storage import ImageStorager
from konabot.plugins.fx_process.math_helper import expand_contours
from konabot.plugins.fx_process.types import SenderInfo, StoredInfo
class ImageFilterImplement:
@ -1126,6 +1128,45 @@ class ImageFilterImplement:
result = Image.alpha_composite(stroke_image, image)
return result
# 基于形状的描边
@staticmethod
def apply_shape_stroke(image: Image.Image, stroke_width: int = 5, stroke_color: str = 'black') -> Image.Image:
if image.mode != 'RGBA':
image = image.convert('RGBA')
img = cv2.cvtColor(np.array(image), cv2.COLOR_RGBA2BGRA)
# 提取alpha通道
alpha = img[:, :, 3]
# 应用阈值创建二值掩码
_, binary_mask = cv2.threshold(alpha, 0.5, 255, cv2.THRESH_BINARY)
# 寻找轮廓
contours, hierarchy = cv2.findContours(
binary_mask,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE
)
# # 减少轮廓点数,以实现尖角效果
# epsilon = 0.01 * cv2.arcLength(contours[0], True)
# contours = [cv2.approxPolyDP(cnt, epsilon, True) for cnt in contours]
# 将轮廓点沿法线方向外扩
expanded_contours = expand_contours(contours, stroke_width)
# 创建描边图像
stroke_img = np.zeros_like(img)
cv2.fillPoly(stroke_img, expanded_contours, ColorHandle.parse_color(stroke_color) + (255,))
# 轮廓图像转为PIL格式
stroke_pil = Image.fromarray(cv2.cvtColor(stroke_img, cv2.COLOR_BGRA2RGBA))
# 合并描边和原图
result = Image.alpha_composite(stroke_pil, image)
return result
# 半调
@staticmethod
def apply_halftone(image: Image.Image, dot_size: int = 5) -> Image.Image:
@ -1186,6 +1227,24 @@ class ImageFilterImplement:
output.putalpha(alpha)
return output
# 设置通道
@staticmethod
def apply_set_channel(image: Image.Image, apply_image: Image.Image, channel: str = 'R', value: int = 255) -> Image.Image:
if image.mode != 'RGBA':
image = image.convert('RGBA')
if apply_image.mode != 'RGBA':
apply_image = apply_image.convert('RGBA')
# 将 apply_image 的通道设置给 image
image_arr = np.array(image)
apply_arr = np.array(apply_image.resize(image.size, Image.Resampling.LANCZOS))
channel_index = {'R':0, 'G':1, 'B':2, 'A':3}.get(channel.upper(), 0)
image_arr[:, :, channel_index] = apply_arr[:, :, channel_index]
return Image.fromarray(image_arr, 'RGBA')
class ImageFilterEmpty: