first commit

This commit is contained in:
douboer
2026-01-20 13:44:28 +08:00
commit 57cd9a1f39
6 changed files with 505 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

36
.gitignore vendored Normal file
View File

@@ -0,0 +1,36 @@
# Build and Release Folders
bin-debug/
bin-release/
[Oo]bj/
[Bb]in/
# Other files and folders
.settings/
node_modules/
public/
myenv/
venv/
package.json
package-lock.json
# Executables
*.swf
*.air
*.ipa
*.apk
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
# should NOT be excluded as they contain compiler settings and other important
# information for Eclipse / Flash Builder.
*.mov
*.mp4
cert/nginx/*.crt
cert/nginx/*.key
*.jpg
*.heic
*.jpeg
*.png

208
README.md Normal file
View File

@@ -0,0 +1,208 @@
# 图片去背景工具
使用rembg库实现的Python去背景工具
## 快速开始
```bash
# 激活虚拟环境
source ~/venv/bin/activate
# 使用默认参数处理images文件夹
python remove_background.py
# 处理单个文件
python remove_background.py input.jpg output.png
# 查看所有参数-m, --model)
不同模型适用于不同场景:
| 模型名称 | 大小 | 适用场景 | 推荐度 |
|---------|------|---------|--------|
| **isnet-general-use** | 179MB | 通用场景 | ⭐⭐⭐⭐⭐ 默认推荐 |
| birefnet-general | 250MB | 通用场景,质量更高 | ⭐⭐⭐⭐⭐ |
| birefnet-portrait | 250MB | 人像专用 | ⭐⭐⭐⭐⭐ |
| u2net | 176MB | 经典通用模型 | ⭐⭐⭐⭐ |
| u2netp | 4.7MB | 快速处理 | ⭐⭐⭐ |
| u2net_human_seg | 176MB | 人物分割 | ⭐⭐⭐⭐ |
| isnet-anime | 179MB | 动漫角色 | ⭐⭐⭐⭐ |
| silueta | 43MB | 精简快速 | ⭐⭐⭐ |
**使用示例**:
```bash
# 使用默认模型
python remove_background.py input.jpg
# 使用人像专用模型
python remove_background.py input.jpg output.png -m birefnet-portrait
# 使用快速模型
python remove_background.py input.jpg output.png -m u2netp
``
```bash
ls -lh ~/.u2net/
```
### 模型大小参考
| 模型名称 | 文件大小 | 特点 |
|---------|---------|------|
| u2net | 176MB | 通用模型 |
| u2netp | 4.7MB | 轻量级,速度快 |
| isnet-general-use | 179MB | 新一代通用,推荐 |
| birefnet-general | ~250MB | 最新通用模型 |
| birefnet-portrait | ~250MB | 人像专用 |
### 手动下载模型(网络问题时)
```bash
# 创建目录
mkdir -p ~/.u2net/
# 下载指定模型以isnet-general-use为例
curl -L "https://github.com/danielgatis/rembg/releases/download/v0.0.0/isnet-general-use.onnx" \
-o ~/.u2net/isnet-general-use.onnx
```
### 清理模型缓存
```bash
# 删除所有已下载的模型
rm -rf ~/.u2net/
# 删除特定模型
rm ~/.u2net/u2net.onnx
```
## 可调整参数说明
### 1. 模型选择 (model_name)
不同模型适用于不同场景:
- **u2net** (默认): 通用模型,适合大多数场景
- **u2netp**: 轻量版,速度更快但精度稍低
- **u2net_human_seg**: 专门用于人物分割
- **silueta**: 精简版u2net (43MB),速度快
- **isnet-general-use**: 新一代通用模型,效果可能更好
- **isnet-anime**: 专门用于动漫角色
- **birefnet-general**: 最新的通用模型,推荐尝试
- **birefnet-portrait**: 专门用于人像
- **birefnet-general-lite**: 轻量版birefnet
**建议**: 如果u2net效果不好试试 `isnet-general-use``birefnet-general`
### 2. Alpha Matting 参数
Alpha Matting 是后处理步骤,可以显著改善边缘质量,特别是头发、毛发等细节。
#### alpha_matting (True/False)
- **作用**: 是否启用alpha matting
- **默认**: False
- **建议**: 如果边缘不自然,启用此选项
#### alpha_matting_foreground_threshold (0-255)
- **作用**: 前景阈值,控制哪些区域被认为是前景
- **默认**: 240
- **调整建议**:
- 值越大(如270): 保留更多细节,但可能保留一些背景
- 值越小(如210): 去除更彻底,但可能丢失细节
- 如果前景被过度去除,增加此值
- 如果背景残留太多,减小此值
#### alpha_matting_background_threshold (0-255)
- **作用**: 背景阈值,控制哪些区域被认为是背景
- **默认**: 10
- **调整建议**:
- 值越大(如20-30): 去除背景更彻底
- 值越小(如5): 保留更多过渡区域
- 如果背景残留,增加此值
#### alpha_matting_erode_size (像素)
- **作用**: 侵蚀大小,用于平滑边缘
- **默认**: 10
- **调整建议**:
- 值越大(如15-20): 边缘更平滑,但可能损失细节
- 值越小(如5-8): 保留更多细节,但边缘可能不够平滑
### 3. Mask后处理 (post_process_mask)
- **作用**: 对mask进行额外的后处理
- **默认**: False
- **建议**: 可以尝试启用看效果是否改善
## 常见问题解决
### 问题1: 前景被过度去除
**解决方案**:
```python
alpha_matting = True
alpha_matting_foreground_threshold = 270 # 增加此值
alpha_matting_background_threshold = 10 # 保持较小
```
### 问题2: 背景残留太多
**解决方案**:
```python
alpha_matting = True
alpha_matting_foreground_threshold = 240 # 保持默认或减小
alpha_matting_background_threshold = 20 # 增加此值
post_process_mask = True # 启用后处理
```
### 问题3: 边缘不自然、有锯齿
**解决方案**:
```python
alpha_matting = True
alpha_matting_erode_size = 15 # 增加平滑程度
```
### 问题4: 毛发、头发细节丢失
**解决方案**:
```python
model_name = "birefnet-portrait" # 使用人像专用模型
alpha_matting = True
alpha_matting_foreground_threshold = 270 # 增加以保留细节
alpha_matting_erode_size = 5 # 减小以保留细节
```
## 推荐配置
### 配置1: 高质量人像
```python
model_name = "birefnet-portrait"
alpha_matting = True
alpha_matting_foreground_threshold = 260
alpha_matting_background_threshold = 15
alpha_matting_erode_size = 10
post_process_mask = True
```
### 配置2: 通用高质量
```python
model_name = "birefnet-general"
alpha_matting = True
alpha_matting_foreground_threshold = 250
alpha_matting_background_threshold = 12
alpha_matting_erode_size = 10
post_process_mask = True
```
### 配置3: 快速处理
```python
model_name = "u2netp"
alpha_matting = False
post_process_mask = False
```
## 测试不同参数
建议按以下顺序调整:
1. 先尝试不同的模型
2. 启用alpha_matting
3. 调整foreground_threshold和background_threshold
4. 最后调整erode_size
每次修改后运行脚本,对比结果。

BIN
output/.DS_Store vendored Normal file

Binary file not shown.

258
remove_background.py Normal file
View File

@@ -0,0 +1,258 @@
"""
图片去背景工具
使用rembg库自动去除图片背景
"""
import os
import argparse
from pathlib import Path
from rembg import remove, new_session
from PIL import Image
# 支持HEIC格式
try:
from pillow_heif import register_heif_opener
register_heif_opener()
HEIC_SUPPORTED = True
except ImportError:
HEIC_SUPPORTED = False
def str2bool(v):
"""将字符串转换为布尔值"""
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('布尔值应为true或false')
def remove_background(input_path, output_path, session=None, **kwargs):
"""
去除图片背景
Args:
input_path: 输入图片路径
output_path: 输出图片路径
session: rembg会话对象可选
**kwargs: 其他参数如alpha_matting相关参数
"""
print(f"正在处理: {input_path}")
# 读取输入图片
input_image = Image.open(input_path)
# 去除背景
output_image = remove(input_image, session=session, **kwargs)
# 保存输出图片
output_image.save(output_path)
print(f"已保存: {output_path}")
def process_images_folder(input_folder, output_folder, model_name="u2net",
alpha_matting=False, alpha_matting_foreground_threshold=240,
alpha_matting_background_threshold=10, alpha_matting_erode_size=10,
post_process_mask=False):
"""
批量处理文件夹中的所有图片
Args:
input_folder: 输入文件夹路径
output_folder: 输出文件夹路径
model_name: 模型名称,可选值:
- u2net (默认): 通用模型
- u2netp: 轻量版u2net
- u2net_human_seg: 人物分割
- silueta: 精简版u2net (43MB)
- isnet-general-use: 新的通用模型
- isnet-anime: 动漫角色高精度分割
- birefnet-general: 通用模型
- birefnet-portrait: 人像模型
alpha_matting: 是否启用alpha matting后处理改善边缘质量
alpha_matting_foreground_threshold: 前景阈值 (0-255),值越大保留越多前景
alpha_matting_background_threshold: 背景阈值 (0-255),值越大去除越多背景
alpha_matting_erode_size: 侵蚀大小,用于平滑边缘
post_process_mask: 是否启用mask后处理
"""
# 创建输出文件夹
Path(output_folder).mkdir(parents=True, exist_ok=True)
# 创建会话(重用会话可以提高性能)
print(f"使用模型: {model_name}")
session = new_session(model_name)
# 支持的图片格式
image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.webp'}
if HEIC_SUPPORTED:
image_extensions.update({'.heic', '.heif'})
else:
print("提示: 未安装pillow-heifHEIC格式不可用。安装方法: pip install pillow-heif")
# 获取所有图片文件
input_path = Path(input_folder)
image_files = [f for f in input_path.iterdir()
if f.is_file() and f.suffix.lower() in image_extensions]
if not image_files:
print(f"{input_folder} 中没有找到图片文件")
return
print(f"找到 {len(image_files)} 张图片,开始处理...")
print(f"Alpha Matting: {'启用' if alpha_matting else '禁用'}")
if alpha_matting:
print(f" - 前景阈值: {alpha_matting_foreground_threshold}")
print(f" - 背景阈值: {alpha_matting_background_threshold}")
print(f" - 侵蚀大小: {alpha_matting_erode_size}")
print(f"Mask后处理: {'启用' if post_process_mask else '禁用'}")
print("-" * 50)
# 处理每张图片
for i, image_file in enumerate(image_files, 1):
try:
# 输出文件名保持原始名称改为PNG格式以支持透明背景
output_filename = image_file.stem + '_nobg.png'
output_path = Path(output_folder) / output_filename
print(f"[{i}/{len(image_files)}] ", end="")
remove_background(
str(image_file),
str(output_path),
session=session,
alpha_matting=alpha_matting,
alpha_matting_foreground_threshold=alpha_matting_foreground_threshold,
alpha_matting_background_threshold=alpha_matting_background_threshold,
alpha_matting_erode_size=alpha_matting_erode_size,
post_process_mask=post_process_mask
)
except Exception as e:
print(f"处理 {image_file.name} 时出错: {e}")
print("-" * 50)
print(f"处理完成!结果保存在 {output_folder} 文件夹中")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='图片去背景工具 - 使用rembg自动去除图片背景',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''
示例用法:
# 使用默认参数处理images文件夹
python remove_background.py
# 处理单个文件
python remove_background.py input.jpg output.png
# 处理指定文件夹
python remove_background.py my_images/ my_output/
# 使用不同模型
python remove_background.py input.jpg output.png -m birefnet-portrait
# 自定义alpha matting参数
python remove_background.py input.jpg output.png -ft 260 -bt 12 -es 5
'''
)
# 必需参数
parser.add_argument('input', nargs='?', default='images',
help='输入文件或文件夹路径(默认: images')
parser.add_argument('output', nargs='?', default=None,
help='输出文件或文件夹路径可选默认为output/')
# 模型选择
parser.add_argument('-m', '--model', default='isnet-general-use',
choices=['u2net', 'u2netp', 'u2net_human_seg', 'silueta',
'isnet-general-use', 'isnet-anime',
'birefnet-general', 'birefnet-general-lite',
'birefnet-portrait', 'birefnet-dis',
'birefnet-hrsod', 'birefnet-cod', 'birefnet-massive'],
help='选择使用的模型 (默认: isnet-general-use)')
# Alpha Matting参数
parser.add_argument('-a', '--alpha-matting', type=str2bool, nargs='?', const=True, default=True,
metavar='true/false',
help='启用alpha matting后处理默认: true。用法: -a 或 -a true 或 -a false')
parser.add_argument('-ft', '--foreground-threshold', type=int, default=245,
help='前景阈值 (0-255),值越大保留越多细节 (默认: 245)')
parser.add_argument('-bt', '--background-threshold', type=int, default=8,
help='背景阈值 (0-255),值越大去除越多背景 (默认: 8)')
parser.add_argument('-es', '--erode-size', type=int, default=2,
help='侵蚀大小,用于平滑边缘,值越大越平滑但可能丢失细节 (默认: 2)')
# 其他选项
parser.add_argument('-p', '--post-process', type=str2bool, nargs='?', const=True, default=True,
metavar='true/false',
help='启用mask后处理默认: true。用法: -p 或 -p true 或 -p false')
args = parser.parse_args()
print("=" * 50)
print("图片去背景工具")
print("=" * 50)
# 判断输入是文件还是文件夹
input_path = Path(args.input)
if not input_path.exists():
print(f"错误: 输入路径不存在: {args.input}")
exit(1)
# 处理单个文件
if input_path.is_file():
# 确定输出路径
if args.output is None:
output_path = input_path.parent / 'output' / (input_path.stem + '_nobg.png')
output_path.parent.mkdir(parents=True, exist_ok=True)
else:
output_path = Path(args.output)
output_path.parent.mkdir(parents=True, exist_ok=True)
print(f"输入文件: {input_path}")
print(f"输出文件: {output_path}")
print(f"模型: {args.model}")
print(f"Alpha Matting: {'启用' if args.alpha_matting else '禁用'}")
if args.alpha_matting:
print(f" - 前景阈值: {args.foreground_threshold}")
print(f" - 背景阈值: {args.background_threshold}")
print(f" - 侵蚀大小: {args.erode_size}")
print(f"Mask后处理: {'启用' if args.post_process else '禁用'}")
print("-" * 50)
# 创建会话
session = new_session(args.model)
# 处理图片
remove_background(
str(input_path),
str(output_path),
session=session,
alpha_matting=args.alpha_matting,
alpha_matting_foreground_threshold=args.foreground_threshold,
alpha_matting_background_threshold=args.background_threshold,
alpha_matting_erode_size=args.erode_size,
post_process_mask=args.post_process
)
print("-" * 50)
print(f"处理完成!结果保存在: {output_path}")
# 处理文件夹
elif input_path.is_dir():
output_folder = args.output if args.output else 'output'
process_images_folder(
str(input_path),
output_folder,
model_name=args.model,
alpha_matting=args.alpha_matting,
alpha_matting_foreground_threshold=args.foreground_threshold,
alpha_matting_background_threshold=args.background_threshold,
alpha_matting_erode_size=args.erode_size,
post_process_mask=args.post_process
)
else:
print(f"错误: 不支持的输入类型: {args.input}")
exit(1)

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
rembg[gpu]
pillow
pillow-heif