胶囊像素:构建带圆角导弧的自适应正交晶格生成艺术引擎

深入解析 Canvas 2D 纯算力生成艺术滤镜:自适应正交多边形合并、有向距离场内外角倒角、双重反差浮雕描边与芯片同心微核算法。

> 一句话结论

传统像素画与马赛克滤镜直接将画面降采样为离散的直角方块,不仅在渐变平坦区制造出杂乱割裂的锯齿阶梯,还会生硬切断主体的轮廓剪影。Yan 在质感工坊中上线的第 31 款滤镜「Capsule Pixel(胶囊像素)」彻底重构了离散网格的呈现方式:通过(1)自适应亮度分级与正交连通域合并,将平坦天空消融为大尺度几何多边形;(2)网格局部有向距离场(Grid SDF),对外凸角与内凹角统一做 R=0.28·cellSize 的平滑圆弧导角;(3)双层波形浮雕反差描边(外层暗缝 + 内层高光线);以及(4)独立格子的同心微核点阵,在浏览器 CPU 上以 40ms 高性能还原兼具芯片电路板与版画等高线的现代生成艺术质感。

告别直角锯齿:直角网格的审美审美疲劳

自 20 世纪 70 年代点阵屏幕诞生以来,像素化(Pixelation)一直是数字艺术最核心的视觉图腾。然而在现代高分辨率显示器上,单纯将照片降采样成低分辨率色块的「朴素马赛克」正面临严峻的审美局限:

  1. 生硬的 90° 直角阶梯折线:无论是人像面部边缘还是自然风景的起伏地平线,斜向轮廓都会被强行锯齿化,破坏主体的有机流动感;
  2. 平坦天空的割裂感:在平滑渐变的天空或雾气区域,相近颜色的方形格子互相堆叠,既缺乏宏观秩序,又显得廉价凌乱;
  3. 死板的黑色网格线:为了突出像素感,许多传统滤镜会机械地在每个方格边缘画一条黑线,导致整个画面被切碎成死气沉沉的方块矩阵。

在设计艺术探索中,台湾生成艺术创作者 William Liang(@william77.fun)提出过一种极具启发性的视觉语言:用程序将摄影作品转译为正交圆角世界——平坦的天空如同层层退晕的梯田等高线,边缘的转折全部带有温润的圆弧导角,细密的水面波光则如同密布微型焊盘与走线的硅基芯片。

为了在 质感工坊 (Texture Studio) 中忠实复刻这一极具先锋感的生成艺术质感,我们构建了 Capsule Pixel(胶囊像素) 引擎。该引擎完全由纯 Canvas 2D 驱动,无需外部依赖或复杂的向量几何库,实现了 100% 确定性的像素级生成效果。

Capsule Pixel 渲染管线架构图
图 1: Yan 胶囊像素引擎的四阶架构流程 — 从亮度色阶合并到网格 SDF 双向圆角倒角、双重波形浮雕反差描边与芯片同心微核生成。


视觉对照:朴素马赛克 vs 胶囊像素引擎

在深入公式细节之前,我们先在包含大片绿色草坡与戴斗笠旅人的高反差测试图上对比两种处理方式:

胶囊像素效果视觉对照:原图 vs 传统像素化 vs 胶囊像素
图 2: 高反差草坡人像裁切对比 — (01) 原始照片;(02) 传统直角马赛克,斗笠与草坡轮廓被生硬锯齿粉碎,天空被切碎成死板格子;(03) Yan 胶囊像素引擎,大平坦区融合成平滑导弧的多边形,人物剪影清晰锐利,细节呈现芯片走线般的机械美感。

仔细观察上图中间的 // 02: 朴素马赛克:

  • 旅人的斗笠与人像剪影完全被锯齿淹没:生硬的直角阶梯割裂了人物轮廓,观者很难在第一时间辨别斗笠边缘的圆润曲线;
  • 草地与天空充斥着无意义的高频方块接缝:原本和谐连贯的背景被分割成数百个刺眼的微小色块。

而在右侧的 // 03: 胶囊像素 中:

  • 天空平缓的受光面自动消融了内部接缝,聚合为宏大的等高线阶梯;
  • 每一个直角拐角无论是凸起还是凹陷,全部拥有精确的圆弧导角(R ≈ 0.28 · cellSize);
  • 紧贴外层暗缝的内嵌亮白高光线,赋予全图一种仿佛在亚克力板上雕刻电路板的立体浮雕质感。

这一质感是如何通过仅 40 毫秒的 CPU 纯像素运算实现的?以下是完整的四阶段算法解析:


阶段 1:自适应色阶聚合与正交连通域合并

胶囊像素的第一步,是消除平坦区域里多余的格子边界。

我们将画面划分为边长为 cellSize(默认 14px,根据图像尺度通过 scaleFor 动态缩放)的正交网格阵列。在每个单元格内,计算平均 RGB 与感知明度:

L = 0.299R + 0.587G + 0.114B

然后,根据对比度参数将明度量化为离散的等高色阶 Q(通常划分为 8 到 16 档):

Q = round((L / 255) × Levels)

当相邻网格单元的量化色阶 Q 相等时,它们在拓扑上被视为属于同一个连通多边形(Polyomino)。这意味着:它们之间的交界线将被彻底抹除。

// 1. 网格单元颜色均值与色阶量化
const gridR = new Float32Array(gw * gh)
const gridG = new Float32Array(gw * gh)
const gridB = new Float32Array(gw * gh)
const gridQ = new Int32Array(gw * gh)

for (let gy = 0; gy < gh; gy++) {
  const y0 = gy * cellSize, y1 = Math.min(h, y0 + cellSize)
  for (let gx = 0; gx < gw; gx++) {
    const x0 = gx * cellSize, x1 = Math.min(w, x0 + cellSize)
    let rSum = 0, gSum = 0, bSum = 0, count = 0
    for (let y = y0; y < y1; y++) {
      const row = y * w * 4
      for (let x = x0; x < x1; x++) {
        const idx = row + x * 4
        rSum += data[idx] ?? 0
        gSum += data[idx + 1] ?? 0
        bSum += data[idx + 2] ?? 0
        count++
      }
    }
    const gIdx = gy * gw + gx
    const r = rSum / count, g = gSum / count, b = bSum / count
    gridR[gIdx] = r; gridG[gIdx] = g; gridB[gIdx] = b
    const lum = 0.299 * r + 0.587 * g + 0.114 * b
    gridQ[gIdx] = Math.round((lum / 255) * levels)
  }
}

这一机制让开阔的天空、湖面与大块阴影自动聚合成宏伟的多边形,保留下来的边界则完美勾勒出画面最关键的明暗转折线。


阶段 2:网格有向距离场(Grid SDF)与双向圆角倒角

如果仅仅合并单元格,得到的依然是一堆边缘带有硬折角的多边形。胶囊像素的灵魂在于对每一个直角进行精密的圆角导弧(Filleting)。

传统 CAD 或矢量图形系统做倒角需要提取轮廓线段并计算圆弧求交,这在单帧几十万像素的实时图像处理中是无法接受的。胶囊像素通过网格拓扑有向距离场(Grid SDF)在单像素扫描中以 O(1) 常数时间完成倒角计算:

设当前像素所在单元格为 (g_x, g_y),格内局部相对坐标为 (u, v) ∈ [0, cellSize-1]^2。我们检查其 8 个正交与对角邻居的色阶是否与当前格不同:diffT, diffB, diffL, diffR, 以及 diffTL, diffTR, diffBL, diffBR。

1. 直边距离

若某条边是区域边界(例如顶部上方邻居色阶不同 diffT == true),则当前点到该直边的垂直距离为 u。

2. 外凸角圆角(Convex Fillet)

当两个正交相邻边均为边界(例如上方与左侧均不同 diffT && diffL),在左上角区域(u < R 且 v < R),直角需要被外凸圆弧切去:
从圆弧圆心 (R, R) 到当前像素的几何距离为 sqrt((R-u)^2 + (R-v)^2)。
因此,当前像素到外凸圆角边界的真实距离更新为:

d = R - sqrt((R - u)^2 + (R - v)^2)

3. 内凹角圆角(Concave Fillet)

当上方和左侧与当前格相同(!diffT && !diffL),但对角线左上方不同(diffTL == true)时,这里形成了一个内凹拐弯角!
内凹圆角的圆心恰好在拐角顶点 (0, 0),当前像素到该拐角边界的距离为:

d = min(d, sqrt(u^2 + v^2))

// 圆角半径设定为格子宽度的 28%
const R = cellSize * 0.28
let d = cellSize * 2 // 初始化为足够大

// 直边距离
if (diffT && u < d) d = u
if (diffB && (cellSize - 1 - u) < d) d = cellSize - 1 - u
if (diffL && v < d) d = v
if (diffR && (cellSize - 1 - v) < d) d = cellSize - 1 - v

// 外凸角倒角
if (diffT && diffL && u < R && v < R) d = R - Math.hypot(R - u, R - v)
if (diffT && diffR && u < R && (cellSize - 1 - v) < R) d = R - Math.hypot(R - u, R - (cellSize - 1 - v))
if (diffB && diffL && (cellSize - 1 - u) < R && v < R) d = R - Math.hypot(R - (cellSize - 1 - u), R - v)
if (diffB && diffR && (cellSize - 1 - u) < R && (cellSize - 1 - v) < R) d = R - Math.hypot(R - (cellSize - 1 - u), R - (cellSize - 1 - v))

// 内凹角倒角
if (!diffT && !diffL && diffTL) d = Math.min(d, Math.hypot(u, v))
if (!diffT && !diffR && diffTR) d = Math.min(d, Math.hypot(u, cellSize - 1 - v))
if (!diffB && !diffL && diffBL) d = Math.min(d, Math.hypot(cellSize - 1 - u, v))
if (!diffB && !diffR && diffBR) d = Math.min(d, Math.hypot(cellSize - 1 - u, cellSize - 1 - v))

这套纯几何闭式解无需任何条件分支跳转或复杂迭代,瞬间赋予了所有多边形如同液体胶囊般的平滑外轮廓。


阶段 3:双重反差波形浮雕描边(Dual-Stroke Relief)

在物理世界中,雕版印刷或蚀刻电路板的边缘不会是一条生硬平涂的单色线条,而是一道具有立体起伏的波形响应:

胶囊像素借鉴了 拉普拉斯高斯算子(Laplacian of Gaussian, LoG) 的墨西哥帽波形分布,在距离边界不同 d 处叠加两重反差描边:

  1. 外侧暗色缝隙(Dark Seam):在紧贴边界的微小带状区域(d < 1.15 · kSize),将原本颜色压暗 80% 以上,模拟出正交拼版交界处的物理凹槽与阴影缝;
  2. 紧贴内侧的高光白线(White Highlight Stroke):在距离边缘约 1.3 \sim 1.8 像素的位置(d ≈ strokeW),以高斯铃形曲线注入一根高亮纯白线条;
  3. 对比度自适应衰减:描边强度与交界两侧相邻格子的实际色彩欧氏距离 \ΔC 成正比。黑塔与天空等高反差边缘呈现饱和的黑白硬边,而天空内部平缓的等高阶梯则自动弱化为半透明微弱暗纹,不会破坏大局平整度。
const kSize = cellSize / 14
const contrastK = Math.max(0.18, Math.min(1.0, (edgeDelta / 75.0) * contrastBoost))

// 1. 外层暗缝 (Seam)
const seamW = Math.max(0.75, 1.15 * kSize)
const seamAlpha = Math.max(0, Math.min(1, seamW - d)) * 0.85 * contrastK
r *= (1 - seamAlpha); g *= (1 - seamAlpha); b *= (1 - seamAlpha)

// 2. 内层亮白高光线 (Stroke)
const strokeW = Math.max(1.3, cellSize * 0.13)
const varStroke = Math.max(0.45, 0.75 * kSize * kSize)
const strokeAlpha = Math.exp(-Math.pow(d - strokeW, 2) / varStroke) * (0.28 + 0.68 * contrastK)
r = r * (1 - strokeAlpha) + 255 * strokeAlpha
g = g * (1 - strokeAlpha) + 255 * strokeAlpha
b = b * (1 - strokeAlpha) + 255 * strokeAlpha

阶段 4:同心内嵌环与芯片微核点阵(Micro Core Nuclei)

在水面反光、树林倒影等高频碎纹区域,网格单元无法与邻居合并,退化为单个独立的 1× 1 方块。如果只是单纯填色,这些小方格会显得扁平单调。

我们为它们赋予了类似芯片焊盘与同心回纹的二级结构:

  • 二级同心内环(Secondary Inset Ring):在 d ≈ 0.28 · cellSize 处施加第二道柔和暗环,让孤立小格子看起来像带有一层深色内衬;
  • 中心微核点阵(Micro Core Nucleus):在每个单元格的几何中心点 ((cellSize-1)/2, (cellSize-1)/2) 植入一颗高斯核点。孤立单元格呈现高亮的白色芯片核,而已合并的大块区域内部则保留暗色微核,巧妙暗示出底层正交晶格的存在。
// 次级内环
const ringW = Math.max(2.8, cellSize * 0.28)
const varRing = Math.max(0.55, 0.8 * kSize * kSize)
const ringAlpha = Math.exp(-Math.pow(d - ringW, 2) / varRing) * 0.35 * contrastK
r *= (1 - ringAlpha); g *= (1 - ringAlpha); b *= (1 - ringAlpha)

// 芯片微核
const distCenter = Math.hypot(u - (cellSize - 1) / 2, v - (cellSize - 1) / 2)
const isIsolated = diffT && diffB && diffL && diffR
const microWeight = isIsolated ? 0.55 : 0.22
const coreR = Math.max(1.0, 1.8 * kSize)
const microAlpha = Math.exp(-Math.pow(distCenter, 2) / (coreR * coreR)) * microWeight * contrastK
r = r * (1 - microAlpha) + (isIsolated ? 255 : 0) * microAlpha
g = g * (1 - microAlpha) + (isIsolated ? 255 : 0) * microAlpha
b = b * (1 - microAlpha) + (isIsolated ? 255 : 0) * microAlpha

横向对比:四种离散栅格几何渲染对比

维度传统像素画 (Pixel Art)沃罗诺伊马赛克 (Voronoi)半调网点 (Halftone)胶囊像素 (Capsule Pixel)
空间拓扑刚性笛卡尔矩形方阵不规则泰森多边形凸网格旋转角度 CMYK 点阵自适应正交连通多边形 (Polyomino)
拐角几何锐利 90° 直角锯齿任意钝角 / 锐角多边形折线连续圆形 / 椭圆点阵内外双向 SDF 平滑圆弧导角 (R=0.28s)
色阶处理简单均值或调色板对齐单胞内单色平涂网点面积调制灰度自适应色阶聚合,平坦区消融接缝
轮廓浮雕无,或单像素黑描边几何单元交界单色缝隙无轮廓(由网点密度感知)墨西哥帽式双重反差浮雕(暗缝+高光)
微观层级扁平实心填充单胞纯色实心墨滴二级同心内环 + 芯片焊盘微核
运行开销单次降采样插值 (<5ms)Delaunay 三角剖分 (O(N\log N))光栅扫描与余弦计算 (~20ms)局部网格拓扑查找 (O(1) 常数时间,~38ms)

在线体验与应用场景

胶囊像素现已作为第 31 款独立滤镜入驻 质感工坊 (Texture Studio)。

推荐尝试的摄影题材

  • 海平面与建筑剪影:长平线与直立灯塔/大桥在胶囊像素下会化身为极具建筑美感的几何阶田;
  • 赛博朋克夜景与车流:霓虹光晕与高反差街道会被转译为发光的印刷电路板(PCB Trace);
  • 山峦云海与等高线:层叠的山脉走势会自动显现出地理测绘等高线地图的秩序与韵律。

调参建议

  • 细节粒度 (Detail):想要清晰的芯片电路板走线与微核,建议设在 50~70;想要大尺度的复古极简抽象色块,拉低至 30~45;
  • 对比度 (Contrast):如果画面光线较平缓,适当拉高对比度可以强行激发更多的等高线层级;
  • 滤镜强度 (Intensity):在 80%~100% 呈现硬核的生成艺术风貌,而在 50%~60% 则能让原图的写实影调与胶囊晶格产生奇妙的双重曝光。

在电脑浏览器中,你可以免注册直接拖入任意照片进行实时调优并导出全分辨率 PNG;而在 Yan 手机端 App 中,该算法已针对移动 GPU 与 CPU 预烘表进行极限优化,支持在相机取景框内以 60fps 实时预览,随手捕捉充满几何美感的赛博胶囊世界。

> 常见问题

什么是「胶囊像素(Capsule Pixel)」?它与传统像素画有何区别?
传统像素画将每个网格像素视为相互孤立的 90° 锐利小正方形。而胶囊像素是一种受电路板布线、等高线地图与极简生成艺术启发的正交几何渲染算子。它在色阶相似的平缓区域融合成连通的正交多边形(Polyomino),并利用有向距离场为所有直角拐角施加温润的圆弧倒角,配合双层黑白高光浮雕描边,呈现出极具秩序感的现代流体晶格美学。
为什么算法不需要复杂的二维多边形轮廓追踪或布尔运算?
算法采用了巧妙的「网格局部有向距离场(Grid SDF)」技术。每个像素仅需查看自身所在的网格单元及周围 3×3 邻域单元的量化色阶,通过判断上下左右与对角线的邻接拓扑关系,在常数时间 O(1) 内闭式计算出当前像素到最近倒角圆弧的精确几何欧氏距离,完全避开了昂贵的多边形轮廓提取、三角剖分或贝塞尔曲线布尔运算。
细节粒度(Detail)与对比度(Contrast)滑杆具体控制什么?
Detail 控制基础网格单元边长(cellSize):低数值对应粗壮的大尺度复古方块,高数值对应细密精巧的微型电路晶格。Contrast 则动态调控亮度量化分级数(Levels)与描边反差系数:调高时天空会细分出更多层细腻等高线,边缘的高光与暗缝反差也更加硬核鲜明。
该算法是在浏览器 GPU 着色器还是在 CPU 上运行?
算法 100% 运行在浏览器 CPU 的 Canvas 2D 纯像素管线中,无需 WebGL 上下文,零外部依赖库。通过预计算邻域拓扑与有向距离场,单帧 1080P 全分辨率渲染在现代设备上仅需约 35~45 毫秒,既保证了 Web 端的即时导出,也保证了移动端 App 实时取景的高帧率。
可以在线免费体验胶囊像素滤镜吗?
可以。在 Yan 的网页质感工坊(yan.yichenlab.com/textures)中切换到 GRID 分类即可免费体验 Capsule Pixel。纯客户端离线计算,不上传任何照片,支持无水印导出最高 1400px 长边的无损 PNG。