用Nano Banana生成透明背景图像

Nano Banana 2的图像质量令人难以置信,但像大多数图像模型一样(除了 gpt-image),它有一个对开发者来说很大的问题:它不支持透明度。

用Nano Banana生成透明背景图像
微信 ezpoda免费咨询:AI编程 | AI模型微调| AI私有化部署
AI工具导航 | Tripo 3D | Meshy AI | ElevenLabs | KlingAI | ArtSpace | Phot.AI | InVideo

最近我一直在尝试使用新的 Nano Banana Pro 2。

多么棒的模型!图像质量令人难以置信,但像大多数图像模型一样(除了 gpt-image),它有一个对开发者来说很大的问题:它不支持透明度。

如果你要求透明背景,你会得到一个纯白色、黑色或棋盘格的背景。它输出的是没有 Alpha 通道的平面 JPEG/PNG。

以下是我如何从 Nano Banana Pro 2 中获取透明素材的方法。

1、尝试 "绿幕"方法

我的第一个直觉是经典的 VFX 方法:

生成一个未来主义头盔,上面有大写文字"HERE IS A HELMET",下方有阴影,背景是纯实的 #00FF00 绿色

我假设我可以像天气预报员一样把绿色抠掉。

但这种技术有它的缺点:

  1. 绿色泄漏: AI 模型倾向于在生成的图像中加入绿色,因为绿色提示会泄漏到生成过程中。
  2. 伪影: AI 模型难以处理大面积的数学上完全平坦的颜色区域。"纯实绿色"实际上是由略微不同的绿色组成的噪点纹理,使得魔棒工具毫无用处。
  3. 光晕: 在某些情况下,如文字或 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
): Promise<void> {
  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 值的黑色像素,这意味着我可以将这些素材放在任何背景颜色上,阴影都能正确混合。
  • 没有绿色光晕: 由于我们不是抠出颜色,所以没有锯齿状的彩色边缘。
  • 更少伪影风险: 黑色和白色背景在大面积纯色区域上不易产生伪影。

原文链接: Generating transparent background images with Nano Banana Pro 2

汇智网翻译整理,转载请标明出处