体验通过开源工具抠图和换背景——基于rembg和pillow

41 阅读2分钟

最近需要用到图片换背景的能力,体验了一下豆包应用,发现效果不太理想,部分细节处理不好,主图的纹理发生了变化。于是考虑去coze自己做一个应用(电商主图背景优化精灵),做完之后发现效果有改善,但是却很容易触发资源点限制,个人免费版只有500/天的资源点,很容易触发限制,因此想尝试在本地通过开源方案实现。

通过资料查找发现rembg和pillow的组合可能是一个较好的入门方案。

抠图 - rembg

Github:github.com/danielgatis…

rembg 是一个用于去除图像背景的 Python 库。它利用先进的机器学习算法来智能地识别图像中的主体和背景,然后将背景去除,只保留想要的前景主体部分,操作相对便捷且效果通常比较出色。

功能特点

  • 自动化程度高:无需手动去精细地描绘或者选择要去除的背景区域等复杂操作,能自动对各类常见的图像进行背景去除处理,适用于人物、物体等多种主体类型的图片。
  • 支持多种输入格式:可以接受常见的图像文件格式如 JPEG、PNG 等作为输入,方便处理不同来源的图像。
  • 应用场景广泛:在电商领域用于商品图片处理,让商品展示更突出;在设计方面,方便设计师快速获取无背景素材用于合成等创作;也常用于证件照处理等场景,去除杂乱背景。

以下是体验的步骤:

  1. 准备新环境:
$ conda create -n aigc python=3.10
$ conda activate aigc
  1. 安装 rembg:
$ pip install "rembg[cpu,cli]"
$ rembg --help
Usage: rembg [OPTIONS] COMMAND [ARGS]...

Options:
  --version  Show the version and exit.
  --help     Show this message and exit.

Commands:
  b  for a byte stream as input
  d  download models
  i  for a file as input
  p  for a folder as input
  s  for a http server
  1. 图片去背景:
$ rembg i ~/Downloads/origin.png ~/Downloads/new.png
Downloading data from 'https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2net.onnx' to file '/Users/xuezhangying/.u2net/u2net.onnx'.
100%|████████████████████████████████████████| 176M/176M [00:00<00:00, 378GB/s]

第一次运行会下载依赖的底层模型:u2net

效果示例:

原图效果图

总体来说,主体基本是扣出来了,但是细节处理不够好,但是达不到令人满意的程度。

换背景 - pillow

Pillow(Python Imaging Library,即 PIL 的一个派生分支)是 Python 中非常强大且常用的图像处理库。它提供了丰富的功能来进行图像的创建、打开、编辑、保存以及多种格式转换等操作。

功能特点

  • 图像操作全面:可以进行图像的缩放、裁剪、旋转、镜像等几何变换;能调整图像的亮度、对比度、色彩平衡等色调相关属性;也支持图像的滤波、模糊等特效处理。
  • 格式支持丰富:能够读取和写入众多图像文件格式,像常见的 BMP、GIF、JPEG、PNG、TIFF 等,便于在不同的图像格式间进行转换和处理。
  • 易于集成与扩展:在 Python 生态中很容易与其他相关的库或者项目进行集成,并且可以通过插件等方式进行功能扩展,开发者可以基于它开发出满足特定需求的图像处理程序。

以下是体验的步骤:

  1. 安装pillow:
$ pip install pillow
  1. 实现融合代码compose.py:
from PIL import Image
import sys
import os

def compose(fg_path, bg_path, out_path):
    # 打开前景图和背景图
    fg = Image.open(fg_path).convert("RGBA")
    bg = Image.open(bg_path).convert("RGBA")

    # 调整前景图大小(缩放为背景宽度的 70%)
    fg_width = int(bg.width * 0.7)
    fg_height = int(fg.height * (fg_width / fg.width))
    fg = fg.resize((fg_width, fg_height), resample=Image.LANCZOS)  # 使用 Image.LANCZOS

    # 将前景图粘贴到背景图中间
    offset_x = (bg.width - fg.width) // 2
    offset_y = (bg.height - fg.height) // 2
    bg.paste(fg, (offset_x, offset_y), fg)

    # 保存结果
    bg.convert("RGB").save(out_path)
    print(f"Composite image saved to: {out_path}")

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: python compose.py <foreground> <background> <output>")
        sys.exit(1)

    compose(sys.argv[1], sys.argv[2], sys.argv[3])

    
  1. 执行图片命令:
$ python compose.py ~/Downloads/product.png ~/Downloads/background.jpeg ~/Downloads/output.jpg

效果示例:

原图商品图效果图

从效果来看,智能说两张图片确实合并在一起了,但是效果不佳,基本不可用。