merge: 像素化 v5 批落籍——白边/噪点三连防线(α腐蚀1环+despeckle+边缘色内插),深底测试条八只全过;PNG透明通道答疑=对话式生图输出压平RGB无解,继续算法路线

This commit is contained in:
DKChan committed 2026-09-27 03:18:26 +08:00
commit f43d4e65e0
1 file changed
+61 -3
+61 -3
View File
@@ -13,7 +13,7 @@ v3 演进(2026-09-27 用户四问题:脏点/模糊/信息丢失/白边):
"""
import sys, os
from collections import deque, Counter
from PIL import Image
from PIL import Image, ImageFilter
SIZES = {"goblin": 96, "giant_spider": 96, "hook_horror": 96,
"bugbear": 128, "duergar": 128,
@@ -237,16 +237,74 @@ def crop_content(im, pad=2):
r, b = min(im.width, r + pad), min(im.height, b + pad)
return im.crop((l, t, r, b))
def despeckle(spr, min_px=10):
"""删小于 min_px 的不透明孤立连通域(噪点)。"""
w, hgt = spr.size
pa = spr.load()
seen = [[False] * w for _ in range(hgt)]
for y0 in range(hgt):
for x0 in range(w):
if seen[y0][x0] or pa[x0, y0][3] == 0:
continue
comp = []
q = deque([(x0, y0)])
seen[y0][x0] = True
while q:
x, y = q.popleft()
comp.append((x, y))
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nx, ny = x + dx, y + dy
if 0 <= nx < w and 0 <= ny < hgt and not seen[ny][nx] and pa[nx, ny][3] != 0:
seen[ny][nx] = True
q.append((nx, ny))
if len(comp) < min_px:
for x, y in comp:
pa[x, y] = (0, 0, 0, 0)
return spr
def edge_inpaint(spr, passes=2):
"""边缘色内插:与透明相邻的不透明像素改色为其内部邻居均值(灭白边,不削轮廓)。"""
w, hgt = spr.size
for _ in range(passes):
pa = spr.load()
fixes = []
for y in range(hgt):
for x in range(w):
c = pa[x, y]
if c[3] == 0:
continue
inner, boundary = [], False
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (1, -1), (-1, 1), (-1, -1)):
nx, ny = x + dx, y + dy
if not (0 <= nx < w and 0 <= ny < hgt):
boundary = True
continue
nc = pa[nx, ny]
if nc[3] == 0:
boundary = True
elif all(pa[nx + ddx, ny + ddy][3] != 0
for ddx, ddy in ((1, 0), (-1, 0), (0, 1), (0, -1))
if 0 <= nx + ddx < w and 0 <= ny + ddy < hgt):
inner.append(nc)
if boundary and inner:
fixes.append((x, y, tuple(sum(ch[i] for ch in inner) // len(inner) for i in range(3))))
for x, y, c in fixes:
r, g, b, a = pa[x, y]
pa[x, y] = (c[0], c[1], c[2], a)
return spr
def pixelize(im, target):
"""BOX 预滤到 4x → 量化 → NEAREST 到 1x(最长边=档位值)。"""
"""BOX 预滤到 4x(α腐蚀2px灭混合带) → 量化 → NEAREST → 降噪点 → 边缘内插。"""
src = crop_content(im)
scale = target * 4 / max(src.size)
pre = src.resize((max(1, round(src.width * scale)), max(1, round(src.height * scale))), Image.BOX)
rgb = pre.convert("RGB")
flat = rgb.quantize(QUANT_COLORS, method=Image.MEDIANCUT).convert("RGB")
out = flat.resize((max(1, round(pre.width / 4)), max(1, round(pre.height / 4))), Image.NEAREST)
a = pre.getchannel("A").resize(out.size, Image.NEAREST).point(lambda v: 255 if v > 128 else 0)
a = pre.getchannel("A").filter(ImageFilter.MinFilter(3)).resize(out.size, Image.NEAREST).point(lambda v: 255 if v > 128 else 0)
out.putalpha(a)
despeckle(out)
edge_inpaint(out)
return out
def strip(spr, path):