用Nano Banana生成透明背景图像

张开发
2026/4/10 7:59:11 15 分钟阅读

分享文章

用Nano Banana生成透明背景图像
最近我一直在尝试使用新的 Nano Banana Pro 2。多么棒的模型图像质量令人难以置信但像大多数图像模型一样除了 gpt-image它有一个对开发者来说很大的问题它不支持透明度。如果你要求透明背景你会得到一个纯白色、黑色或棋盘格的背景。它输出的是没有 Alpha 通道的平面 JPEG/PNG。以下是我如何从 Nano Banana Pro 2 中获取透明素材的方法。1、尝试 绿幕方法我的第一个直觉是经典的 VFX 方法生成一个未来主义头盔上面有大写文字HERE IS A HELMET下方有阴影背景是纯实的 #00FF00 绿色我假设我可以像天气预报员一样把绿色抠掉。但这种技术有它的缺点绿色泄漏AI 模型倾向于在生成的图像中加入绿色因为绿色提示会泄漏到生成过程中。伪影AI 模型难以处理大面积的数学上完全平坦的颜色区域。纯实绿色实际上是由略微不同的绿色组成的噪点纹理使得魔棒工具毫无用处。光晕在某些情况下如文字或 UI 元素我会发现所有东西周围都有一个锯齿状的 1px 绿色光晕。以一种可靠的系统性方式消除这一点很困难。我意识到色度抠图并不能为透明度提供可靠的、干净的方法。2、解决方案差异遮罩理论很简单如果你有一个完全相同的像素显示在纯黑背景和纯白背景上你可以使用数学来计算那个像素有多透明。Nano Banana Pro 2 在图像编辑方面表现出色所以我想到嘿这可能是可行的3、工作流程技巧在于模型的图像编辑能力。步骤 1在白色背景上生成首先我用标准提示生成素材。一个复杂、详细的未来主义 UI类似 HUD有不同的组件透明效果背景是纯实的白色 #FFFFFF步骤 2编辑为黑色背景我将输出结果反馈回模型并附上编辑请求。将白色背景改为纯实的黑色 #000000。保持其他所有内容完全不变因为模型在编辑过程中会尝试保留主题所以我最终得到两个完美对齐的图像一个在白色背景上一个在黑色背景上。步骤 3应用差异遮罩现在让我们使用这两张图像来创建最终的透明图像npx tsx extract_alpha.ts input-white.jpeg input-black.jpeg output.png结果绝对完美4、代码我写了一个使用 sharp 库处理这两张图像的小型 TypeScript 工具。它逐像素比较它们以恢复 Alpha 通道。以下是我使用的函数import sharp from sharp; import fs from fs/promises; export interface RGB { r: number; g: number; b: number; } const BLACK: RGB { r: 0, g: 0, b: 0 }; const WHITE: RGB { r: 255, g: 255, b: 255 }; export async function extractAlphaTwoPass( imgOnWhitePath: string, imgOnBlackPath: string, outputPath: string ): Promisevoid { const img1 sharp(imgOnWhitePath); const img2 sharp(imgOnBlackPath); // 确保我们处理的是原始像素数据 const { data: dataWhite, info: meta } await img1 .ensureAlpha() .raw() .toBuffer({ resolveWithObject: true }); const { data: dataBlack } await img2 .ensureAlpha() .raw() .toBuffer({ resolveWithObject: true }); if (dataWhite.length ! dataBlack.length) { throw new Error(尺寸不匹配图像必须大小相同); } const outputBuffer Buffer.alloc(dataWhite.length); // 白色 (255,255,255) 和黑色 (0,0,0) 之间的距离 // sqrt(255^2 255^2 255^2) ≈ 441.67 const bgDist Math.sqrt(3 * 255 * 255); for (let i 0; i meta.width * meta.height; i) { const offset i * 4; // 获取两个图像中相同像素的 RGB 值 const rW dataWhite[offset]; const gW dataWhite[offset 1]; const bW dataWhite[offset 2]; const rB dataBlack[offset]; const gB dataBlack[offset 1]; const bB dataBlack[offset 2]; // 计算两个观察到的像素之间的距离 const pixelDist Math.sqrt( Math.pow(rW - rB, 2) Math.pow(gW - gB, 2) Math.pow(bW - bB, 2) ); // 公式 // 如果像素 100% 不透明它在黑色和白色上看起来一样 (pixelDist 0)。 // 如果像素 100% 透明它看起来完全像背景 (pixelDist bgDist)。 // 因此 let alpha 1 - (pixelDist / bgDist); // 将结果限制在 0-1 范围内 alpha Math.max(0, Math.min(1, alpha)); // 颜色恢复 // 我们使用黑色背景上的图像来恢复颜色除以 alpha // 来取消预乘提亮半透明像素 let rOut 0, gOut 0, bOut 0; if (alpha 0.01) { // 从黑色版本恢复前景颜色 // (C - (1-alpha) * BG) / alpha // 由于 BG 是黑色 (0,0,0)这简化为 C / alpha rOut rB / alpha; gOut gB / alpha; bOut bB / alpha; } outputBuffer[offset] Math.round(Math.min(255, rOut)); outputBuffer[offset 1] Math.round(Math.min(255, gOut)); outputBuffer[offset 2] Math.round(Math.min(255, bOut)); outputBuffer[offset 3] Math.round(alpha * 255); } await sharp(outputBuffer, { raw: { width: meta.width, height: meta.height, channels: 4 } }) .png() .toFile(outputPath); }5、为什么这很棒结果让我震惊。它是一个完美的透明图像。玻璃有效我生成的房屋中半透明窗户实际上变得透明了。阴影有效物体投射的微弱阴影被保留为带有低 Alpha 值的黑色像素这意味着我可以将这些素材放在任何背景颜色上阴影都能正确混合。没有绿色光晕由于我们不是抠出颜色所以没有锯齿状的彩色边缘。更少伪影风险黑色和白色背景在大面积纯色区域上不易产生伪影。原文链接用Nano Banana生成透明背景图像 - 汇智网

更多文章