🔥 还在为图片修复头疼?这个开源工具让AI修图变得像PS一样简单
实测可商用!一款支持40+模型的本地图片修复神器,再也不用担心隐私泄露
一、为什么这个项目值得关注
1.1 图像修复的痛点
在日常工作和创意设计中,你是否遇到过这些情况:
- 照片里突然闯入的路人,想完美抹除却总是留下痕迹
- 老照片破损,想要修复却不知道从何下手
- 想给图片扩展画面,却担心AI生成的内容不自然
- 使用在线修图工具时,总担心自己的图片被滥用
这些问题的核心在于:缺乏一个本地化、免费、功能强大的图像修复解决方案。
1.2 IOPaint 是什么
IOPaint 是由开发者 Sanster 开源的一个自托管图像修复(Inpainting)和扩展(Outpainting)工具。它的核心特点是:
项目地址:https://github.com/Sanster/IOPaint
主要语言:Python
支持平台:Windows、MacOS、Linux
1.3 四大核心优势
| 优势 | 详细说明 |
|---|---|
| 🔒 隐私安全 | 所有处理都在本地完成,图片不会上传到任何服务器 |
| 🎨 模型丰富 | 支持 40+ 种 AI 模型,包括 LaMa、MAT、LDM 等主流算法 |
| 💻 跨平台 | 支持 Windows、Mac、Linux 系统 |
| 🆓 完全免费 | 开源项目,可自由使用和二次开发 |
1.4 与其他工具的对比
对比维度 IOPaint 在线工具 Photoshop AI
---------------------------------------------------------------
隐私保护 ✅ 本地处理 ❌ 上传云端 ✅ 本地处理
模型数量 40+ 1-2 内置
使用成本 免费 按次收费 订阅制
学习曲线 低 低 高
扩展功能 丰富 有限 有限
开源可定制 ✅ ❌ ❌
二、环境搭建:5分钟快速上手
2.1 系统要求
在开始之前,确认你的电脑满足以下基本要求:
最低配置:
- 显卡:NVIDIA GTX 1060 4GB 或同等性能
- 内存:8GB
- 硬盘:10GB 可用空间
推荐配置:
- 显卡:NVIDIA RTX 3060 8GB 或更高
- 内存:16GB
- 硬盘:20GB 可用空间(用于存储模型)
2.2 安装方式一:Docker(推荐新手)
如果你熟悉 Docker,这是最简单的方式:
# 拉取最新镜像
docker pull sanster/iopaint
# 运行容器
docker run -d \
--name iopaint \
-p 8080:8080 \
-v ./output:/app/output \
-v ./models:/root/.cache/torch/hub/models \
sanster/iopaint
# 访问 http://localhost:8080 即可使用
2.3 安装方式二:Python 虚拟环境
步骤 1:检查 Python 环境
# 检查 Python 版本(需要 3.8 或更高)
python --version
# 如果没有 Python,先安装
# Ubuntu/Debian:
sudo apt update && sudo apt install python3 python3-pip python3-venv
# Windows: 从 python.org 下载安装包
步骤 2:创建虚拟环境
# 创建名为 iopaint_env 的虚拟环境
python -m venv iopaint_env
# 激活虚拟环境
# Linux/Mac:
source iopaint_env/bin/activate
# Windows:
iopaint_env\Scripts\activate
步骤 3:安装 IOPaint
# 升级 pip
pip install --upgrade pip
# 安装 IOPaint
pip install iopaint
# 如果你使用 NVIDIA 显卡,安装 CUDA 版本
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
2.4 安装方式三:手动安装(开发者版本)
# 克隆仓库
git clone https://github.com/Sanster/IOPaint.git
cd IOPaint
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# 安装依赖
pip install -r requirements.txt
# 安装开发依赖(可选)
pip install -r requirements-dev.txt
2.5 验证安装
# 运行 IOPaint
iopaint run --host 0.0.0.0 --port 8080
如果一切正常,你应该能看到类似输出:
========================================
IOPaint v1.x.x 启动成功!
访问地址: http://localhost:8080
========================================
现在,打开浏览器访问 http://localhost:8080 ,你应该能看到 IOPaint 的 Web 界面。
三、核心功能详解
3.1 功能架构概览
IOPaint 提供了完整的图像修复解决方案,主要包括以下功能模块:
┌─────────────────────────────────────────────────┐
│ IOPaint 界面 │
├─────────────────────────────────────────────────┤
│ 📷 图像导入 │ 🎨 模型选择 │
│ ✏️ 涂抹遮罩 │ ⚙️ 参数调整 │
│ 🔧 图像编辑 │ 💾 导出保存 │
└─────────────────────────────────────────────────┘
3.2 支持的 AI 模型
IOPaint 支持多种先进的图像修复算法,下面详细介绍:
3.2.1 LaMa(快速且效果稳定)
模型名称:LaMa
适用场景:通用图像修复
显存需求:约 4GB
处理速度:快
特点:对边缘处理较好,适合大部分场景
代码示例 – 使用 LaMa 模型:
from iopaint.api import IOService
from iopaint.schema import ModelConfig
# 初始化服务
service = IOService()
# 配置模型
config = ModelConfig(
model_name="lama", # 使用 LaMa 模型
device="cuda", # 使用 GPU 加速
model_path=None # 自动下载模型
)
# 加载图像和遮罩
image = service.load_image("input.jpg")
mask = service.load_mask("mask.png")
# 执行修复
result = service.inpaint(image, mask, config)
# 保存结果
service.save_image(result, "output.jpg")
3.2.2 MAT(细节丰富)
模型名称:MAT(MATNet)
适用场景:需要保留细节的高质量修复
显存需求:约 6GB
处理速度:中等
特点:能更好地保留纹理细节
代码示例 – 使用 MAT 模型:
from iopaint.api import IOService
from iopaint.schema import ModelConfig, HDStrategy
config = ModelConfig(
model_name="mat",
device="cuda",
# 高清修复策略
hd_strategy=HDStrategy.ORIGINAL,
hd_strategy_crop_margin=32,
hd_strategy_crop_size=512,
# 修复相关参数
l2_zero_thresh=0.5,
use_cudnn=True
)
service = IOService()
result = service.inpaint(image, mask, config)
3.2.3 LDPM(处理大面积缺失)
模型名称:LDPM(Latent Diffusion Prior)
适用场景:大面积缺失修复、创意生成
显存需求:约 8GB
处理速度:较慢
特点:生成能力强,适合创意场景
代码示例 – 使用 LDPM 模型:
config = ModelConfig(
model_name="ldpm",
device="cuda",
# 控制生成的多样性
ddim_steps=50,
guidance_scale=7.5,
# 随机种子(固定可复现)
seed=42
)
result = service.inpaint(image, mask, config)
3.2.4 支持模型完整列表
| 模型名称 | 用途 | 显存需求 | 推荐场景 |
|---|---|---|---|
| lama | 通用修复 | 4GB | 日常使用首选 |
| mat | 细节修复 | 6GB | 高清图片 |
| sd1.5 | 通用生成 | 4GB | 创意扩展 |
| sd2 | 高清生成 | 6GB | 高质量输出 |
| instruct-pix2pix | 指令编辑 | 6GB | 文本引导编辑 |
| plugin-remove-bg | 背景移除 | 2GB | 抠图 |
| plugin-rembg | 背景移除 | 2GB | 抠图备选 |
3.3 图像编辑功能
3.3.1 遮罩工具
IOPaint 提供了专业的遮罩编辑功能:
# 遮罩创建示例
from iopaint.schema import BrushConfig
brush_config = BrushConfig(
size=30, # 画笔大小
mode="erase", # erase 或 fill
hardness=0.8, # 边缘硬度
smooth_level=3 # 平滑级别
)
3.3.2 图像扩展(Outpainting)
支持向图像四周扩展内容:
# 扩展图像示例
from iopaint.schema import OutpaintConfig
outpaint_config = OutpaintConfig(
direction="right", # 扩展方向
pixels=256, # 扩展像素数
model_name="sd1.5", # 使用的模型
prompt="seamless continuation of the scene"
)
result = service.outpaint(image, outpaint_config)
3.3.3 背景移除
# 背景移除示例
from iopaint.api import BackgroundRemover
remover = BackgroundRemover(model_name="u2net")
# 移除背景,返回透明图像
result = remover.remove(image, return_mask=False)
# 只返回遮罩
mask_only = remover.remove(image, return_mask=True)
3.4 参数调整技巧
不同的参数设置会产生截然不同的效果:
from iopaint.schema import InpaintRequest
# 创建修复请求
request = InpaintRequest(
# === 基础参数 ===
image=image, # 原图
mask=mask, # 遮罩
model="lama", # 模型选择
# === 生成参数 ===
prompt="", # 文本提示(某些模型需要)
negative_prompt="blurry, low quality", # 负面提示
guidance_scale=7.5, # 生成引导强度(1-20)
# === 高级参数 ===
hd_strategy="ORIGINAL", # 高清处理策略
hd_strategy_crop_size=512, # 裁剪大小
sd_steps=50, # 采样步数
# === 控制参数 ===
crossattend_uniform=False,
controlnet_model=None,
controlnet_weight=1.0
)
四、实战教程:从入门到精通
4.1 教程一:去除照片中的路人
场景:你在景点拍照,但画面中突然闯入了一个路人。
4.1.1 准备图片
首先,准备一张需要处理的图片:
import cv2
import numpy as np
from PIL import Image
# 读取图片
image_path = "tourist_photo.jpg"
image = Image.open(image_path)
# 检查图片尺寸
print(f"图片尺寸: {image.size}")
print(f"图片模式: {image.mode}")
# 如果图片太大,先缩小(加快处理速度)
max_size = 1024
if max(image.size) > max_size:
ratio = max_size / max(image.size)
new_size = (int(image.size[0] * ratio), int(image.size[1] * ratio))
image = image.resize(new_size, Image.LANCZOS)
print(f"已调整为: {new_size}")
4.1.2 创建遮罩
用代码创建一个简单的遮罩:
# 创建一个与图片相同大小的遮罩(黑色 = 不修复,白色 = 修复)
mask = Image.new("L", image.size, 0)
# 在遮罩上绘制要修复的区域
from PIL import ImageDraw
draw = ImageDraw.Draw(mask)
# 假设路人位置在图片中心附近
# 绘制一个圆形区域(可以根据实际情况调整)
center_x, center_y = image.size[0] // 2, image.size[1] // 2
radius = 100
# 画一个白色的圆表示要修复的区域
draw.ellipse(
[center_x - radius, center_y - radius,
center_x + radius, center_y + radius],
fill=255
)
# 保存遮罩查看
mask.save("mask_circle.png")
实际上,在 IOPaint 的 Web 界面中,你可以直接用画笔涂抹选择区域,更加直观方便。
4.1.3 执行修复
from iopaint.api import IOService
from iopaint.schema import ModelConfig
# 初始化服务
service = IOService()
# 配置模型 - LaMa 速度快,效果好
config = ModelConfig(
model_name="lama",
device="cuda", # 使用 GPU
# 如果没有 GPU,改为 device="cpu",但速度会很慢
)
# 执行修复
result = service.inpaint(image, mask, config)
# 保存结果
result.save("result_no_stranger.jpg")
print("修复完成!")
4.1.4 完整脚本
"""
图片修复脚本 - 去除路人
使用方法:python remove_object.py --input 输入图片 --output 输出图片
"""
import argparse
from pathlib import Path
from PIL import Image, ImageDraw
from iopaint.api import IOService
from iopaint.schema import ModelConfig
def create_mask(image_size, regions):
"""
根据给定的区域创建遮罩
参数:
image_size: (width, height) 图片尺寸
regions: 区域列表,每个区域为 (x, y, w, h) 或 (x, y, r)
返回:
遮罩图像
"""
mask = Image.new("L", image_size, 0)
draw = ImageDraw.Draw(mask)
for region in regions:
if len(region) == 3:
# 圆形区域 (x, y, radius)
x, y, r = region
draw.ellipse([x-r, y-r, x+r, y+r], fill=255)
else:
# 矩形区域 (x, y, w, h)
x, y, w, h = region
draw.rectangle([x, y, x+w, y+h], fill=255)
return mask
def remove_objects(image_path, output_path, regions, model="lama"):
"""
去除图片中的指定物体
参数:
image_path: 输入图片路径
output_path: 输出图片路径
regions: 要去除的区域列表
model: 使用的模型名称
"""
# 加载图片
image = Image.open(image_path).convert("RGB")
# 创建遮罩
mask = create_mask(image.size, regions)
# 初始化服务
service = IOService()
config = ModelConfig(model_name=model, device="cuda")
# 执行修复
result = service.inpaint(image, mask, config)
# 保存结果
result.save(output_path)
print(f"✅ 已保存到: {output_path}")
# 主程序入口
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="图片物体去除工具")
parser.add_argument("--input", "-i", required=True, help="输入图片路径")
parser.add_argument("--output", "-o", default="output.jpg", help="输出图片路径")
parser.add_argument("--model", "-m", default="lama", help="使用的模型")
# 可以添加多个矩形或圆形区域
# 格式: x,y,w,h (矩形) 或 x,y,r (圆形)
parser.add_argument("--regions", "-r", nargs="+", default=[],
help="区域坐标,如: 100,100,50,50")
args = parser.parse_args()
# 解析区域参数
parsed_regions = []
for region in args.regions:
coords = list(map(int, region.split(",")))
if len(coords) == 4:
# 矩形:转换为 (x, y, w, h) 格式
parsed_regions.append(tuple(coords))
elif len(coords) == 3:
# 圆形:转换为 (x, y, r) 格式
parsed_regions.append(tuple(coords))
remove_objects(args.input, args.output, parsed_regions, args.model)
使用示例:
# 去除一个矩形区域的物体
python remove_object.py -i photo.jpg -o result.jpg -r "100,100,80,80"
# 去除多个区域
python remove_object.py -i photo.jpg -o result.jpg -r "100,100,50,50" "300,200,40,40"
# 使用圆形区域(圆形需要3个参数:x, y, radius)
python remove_object.py -i photo.jpg -o result.jpg -r "200,200,60"
4.2 教程二:老照片修复
场景:有一张破损的老照片,想要修复划痕和缺失部分。
4.2.1 分析老照片的问题
from PIL import Image, ImageFilter
import numpy as np
def analyze_old_photo(image_path):
"""分析老照片的问题"""
image = Image.open(image_path).convert("RGB")
# 转换为 numpy 数组进行分析
img_array = np.array(image)
# 检测问题区域
# 1. 低对比度检测
gray = np.mean(img_array, axis=2)
contrast = np.std(gray)
# 2. 噪点检测
noise_level = np.std(gray[1:] - gray[:-1]) # 简单的边缘噪声估计
# 3. 颜色退化检测
r_mean, g_mean, b_mean = np.mean(img_array, axis=(0,1))
print(f"对比度分数: {contrast:.2f}")
print(f"噪点等级: {noise_level:.2f}")
print(f"颜色偏移: R={r_mean:.1f}, G={g_mean:.1f}, B={b_mean:.1f}")
# 评估照片状态
if contrast < 30:
print("⚠️ 照片对比度较低,建议先增强对比度")
if noise_level > 15:
print("⚠️ 检测到较多噪点")
return image
# 分析照片
analyze_old_photo("old_photo.jpg")
4.2.2 照片预处理
from PIL import Image, ImageEnhance, ImageFilter
def preprocess_old_photo(image_path, output_path):
"""
预处理老照片
包括:去噪、对比度增强、色彩校正
"""
image = Image.open(image_path)
# === 步骤1:去噪 ===
# 使用中值滤波去除小的噪点
denoised = image.filter(ImageFilter.MedianFilter(size=3))
# === 步骤2:对比度增强 ===
enhancer = ImageEnhance.Contrast(denoised)
enhanced = enhancer.enhance(1.5) # 1.5倍对比度
# === 步骤3:亮度调整 ===
enhancer = ImageEnhance.Brightness(enhanced)
brightened = enhancer.enhance(1.1) # 稍微提亮
# === 步骤4:色彩校正 ===
enhancer = ImageEnhance.Color(brightened)
color_corrected = enhancer.enhance(1.2)
# === 步骤5:锐化 ===
sharpened = color_corrected.filter(
ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3)
)
# 保存预处理结果
sharpened.save(output_path)
print(f"预处理完成: {output_path}")
return sharpened
# 执行预处理
preprocessed = preprocess_old_photo("old_photo.jpg", "old_photo_preprocessed.jpg")
4.2.3 创建智能遮罩
import cv2
import numpy as np
from PIL import Image
def create_smart_mask(image, sensitivity=30):
"""
自动检测照片中需要修复的区域
参数:
image: PIL Image 对象
sensitivity: 检测灵敏度(值越大检测越多)
"""
# 转换为灰度图
gray = np.array(image.convert("L"))
# 使用自适应阈值检测暗区和亮区
# 这些区域通常是划痕、污渍或缺失部分
# 检测暗区域(可能是污渍或划痕)
dark_mask = gray < sensitivity
dark_regions = dark_mask.astype(np.uint8) * 255
# 检测亮区域(可能是反光或氧化)
bright_mask = gray > (255 - sensitivity)
bright_regions = bright_mask.astype(np.uint8) * 255
# 合并两个遮罩
combined = np.maximum(dark_regions, bright_regions)
# 形态学操作 - 膨胀和腐蚀,使遮罩更加平滑
kernel = np.ones((5, 5), np.uint8)
combined = cv2.dilate(combined, kernel, iterations=1)
combined = cv2.erode(combined, kernel, iterations=1)
# 中值滤波去除孤立噪点
combined = cv2.medianBlur(combined, 5)
return Image.fromarray(combined)
# 创建自动遮罩
auto_mask = create_smart_mask(preprocessed, sensitivity=40)
# 混合遮罩:使用自动检测 + 手动绘制
# 保存自动检测结果供参考
auto_mask.save("auto_detected_mask.png")
print("自动检测遮罩已保存")
4.2.4 执行修复
from iopaint.api import IOService
from iopaint.schema import ModelConfig
def restore_old_photo(image_path, mask_path, output_path, model="mat"):
"""
修复老照片
参数:
image_path: 预处理后的照片路径
mask_path: 遮罩路径
output_path: 输出路径
model: 使用的模型
"""
# 加载图片和遮罩
image = Image.open(image_path).convert("RGB")
mask = Image.open(mask_path).convert("L")
# 初始化服务
service = IOService()
# MAT 模型对细节保留更好,适合老照片修复
config = ModelConfig(
model_name=model,
device="cuda",
# 高清策略
hd_strategy="ORIGINAL",
l2_zero_thresh=0.5
)
# 执行修复
result = service.inpaint(image, mask, config)
# 保存结果
result.save(output_path)
print(f"✅ 修复完成: {output_path}")
return result
# 执行修复
restored = restore_old_photo(
"old_photo_preprocessed.jpg",
"mask_for_restoration.png", # 你可以用画笔手动绘制遮罩
"old_photo_restored.jpg",
model="mat" # MAT 模型保留更多细节
)
4.2.5 完整的老照片修复流程
"""
老照片修复完整流程
"""
import cv2
import numpy as np
from PIL import Image, ImageEnhance, ImageFilter
from iopaint.api import IOService
from iopaint.schema import ModelConfig
class OldPhotoRestorer:
"""老照片修复类"""
def __init__(self, device="cuda"):
self.device = device
self.service = IOService()
def preprocess(self, image):
"""图像预处理"""
# 去噪
denoised = image.filter(ImageFilter.MedianFilter(size=3))
# 增强对比度
enhanced = ImageEnhance.Contrast(denoised).enhance(1.5)
# 调整亮度
brightened = ImageEnhance.Brightness(enhanced).enhance(1.1)
# 色彩校正
color_corrected = ImageEnhance.Color(brightened).enhance(1.2)
# 锐化
sharpened = color_corrected.filter(
ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3)
)
return sharpened
def create_mask(self, image):
"""创建修复遮罩"""
gray = np.array(image.convert("L"))
# 自动检测问题区域
dark_regions = (gray < 30).astype(np.uint8) * 255
bright_regions = (gray > 225).astype(np.uint8) * 255
combined = np.maximum(dark_regions, bright_regions)
# 形态学处理
kernel = np.ones((5, 5), np.uint8)
combined = cv2.dilate(combined, kernel, iterations=1)
combined = cv2.erode(combined, kernel, iterations=1)
combined = cv2.medianBlur(combined, 5)
return Image.fromarray(combined)
def restore(self, image_path, output_path, use_auto_mask=True,
mask_path=None, model="mat"):
"""
执行完整的修复流程
参数:
image_path: 输入图片路径
output_path: 输出图片路径
use_auto_mask: 是否使用自动遮罩
mask_path: 手动遮罩路径(可选)
model: 使用的模型
"""
# 1. 加载图片
print("📷 加载图片...")
image = Image.open(image_path).convert("RGB")
# 2. 预处理
print("🔧 预处理中...")
preprocessed = self.preprocess(image)
preprocessed.save("step1_preprocessed.jpg")
# 3. 创建/加载遮罩
print("🎨 创建遮罩...")
if use_auto_mask:
mask = self.create_mask(preprocessed)
else:
mask = Image.open(mask_path).convert("L")
mask.save("step2_mask.jpg")
# 4. 执行修复
print("✨ AI 修复中(这可能需要几分钟)...")
config = ModelConfig(
model_name=model,
device=self.device,
hd_strategy="ORIGINAL"
)
result = self.service.inpaint(preprocessed, mask, config)
# 5. 后处理 - 轻微去噪
print("💫 后处理...")
final = result.filter(ImageFilter.SurfaceBlur(radius=1))
# 6. 保存结果
final.save(output_path)
print(f"✅ 修复完成!结果已保存到: {output_path}")
return final
# 使用示例
if __name__ == "__main__":
restorer = OldPhotoRestorer(device="cuda")
restorer.restore(
image_path="my_old_photo.jpg",
output_path="restored_photo.jpg",
use_auto_mask=True,
model="mat"
)
4.3 教程三:智能扩图(Outpainting)
场景:想把图片扩展到更宽的画幅,让AI帮你生成缺失的内容。
4.3.1 基础扩图
from iopaint.api import IOService
from iopaint.schema import OutpaintConfig, ModelConfig
def expand_image_basic(image_path, output_path, direction="right", pixels=512):
"""
基础扩图功能
参数:
image_path: 输入图片路径
output_path: 输出图片路径
direction: 扩展方向 ("left", "right", "top", "bottom")
pixels: 扩展的像素数
"""
# 加载图片
image = Image.open(image_path).convert("RGB")
# 初始化服务
service = IOService()
# 配置扩图参数
config = OutpaintConfig(
direction=direction,
pixels=pixels,
model_name="sd1.5" # 使用 Stable Diffusion 进行扩图
)
# 执行扩图
result = service.outpaint(image, config)
# 保存结果
result.save(output_path)
print(f"✅ 扩图完成: {output_path}")
# 使用示例
expand_image_basic(
image_path="portrait.jpg",
output_path="portrait_expanded.jpg",
direction="right",
pixels=512
)
4.3.2 四方向扩展(创建全景图)
from iopaint.api import IOService
from iopaint.schema import OutpaintConfig, ModelConfig
from PIL import Image
def expand_all_directions(image_path, output_path, pixels_per_side=256):
"""
四个方向同时扩展,创建全景效果
参数:
image_path: 输入图片路径
output_path: 输出图片路径
pixels_per_side: 每个方向扩展的像素数
"""
# 加载图片
image = Image.open(image_path).convert("RGB")
w, h = image.size
service = IOService()
# 扩展方向顺序(顺时针)
directions = ["left", "top", "right", "bottom"]
# 每次扩展后的新图片
current_image = image.copy()
for i, direction in enumerate(directions):
print(f"🔄 正在扩展 {direction} 方向 ({i+1}/{len(directions)})...")
config = OutpaintConfig(
direction=direction,
pixels=pixels_per_side,
model_name="sd1.5",
guidance_scale=7.5,
ddim_steps=30
)
current_image = service.outpaint(current_image, config)
# 保存中间步骤(方便调试)
current_image.save(f"step_{i+1}_{direction}.jpg")
current_image.save(output_path)
print(f"✅ 全景扩展完成: {output_path}")
print(f"最终尺寸: {current_image.size}")
return current_image
# 使用示例 - 创建全景效果
expand_all_directions(
image_path="landscape.jpg",
output_path="landscape_panorama.jpg",
pixels_per_side=300
)
4.3.3 带提示词的智能扩图
def expand_with_prompt(image_path, output_path, direction, pixels,
prompt, negative_prompt=""):
"""
使用文本提示词引导扩图
参数:
image_path: 输入图片路径
output_path: 输出图片路径
direction: 扩展方向
pixels: 扩展像素数
prompt: 正面提示词,描述你想要生成的内容
negative_prompt: 负面提示词,描述你不想要的内容
"""
image = Image.open(image_path).convert("RGB")
service = IOService()
# 创建带提示词的配置
config = OutpaintConfig(
direction=direction,
pixels=pixels,
model_name="sd1.5",
# 提示词设置
prompt=prompt,
negative_prompt=negative_prompt,
# 生成参数
guidance_scale=7.5,
ddim_steps=50,
# 控制随机性
seed=-1 # -1 表示随机,指定数字可复现
)
result = service.outpaint(image, config)
result.save(output_path)
return result
# 使用示例 - 扩展风景照片
expand_with_prompt(
image_path="mountain.jpg",
output_path="mountain_extended.jpg",
direction="right",
pixels=512,
prompt="continue the mountain landscape, blue sky with clouds, green hills",
negative_prompt="buildings, people, cars, text, watermark"
)
4.3.4 创意扩图 – 不同风格的扩展
def expand_with_style(image_path, output_path, direction, style="realistic"):
"""
不同风格的扩图
参数:
image_path: 输入图片路径
output_path: 输出图片路径
direction: 扩展方向
style: 风格 ("realistic", "artistic", "fantasy")
"""
# 不同风格的提示词配置
style_configs = {
"realistic": {
"prompt": "realistic continuation, natural lighting, high quality photo",
"negative": "cartoon, anime, drawing, painting, artificial",
"guidance_scale": 7.5,
"steps": 50
},
"artistic": {
"prompt": "oil painting style, artistic interpretation, museum quality",
"negative": "photograph, realistic, low quality",
"guidance_scale": 10.0,
"steps": 60
},
"fantasy": {
"prompt": "magical fantasy landscape, ethereal glow, mystical atmosphere",
"negative": "modern buildings, cars, power lines, mundane objects",
"guidance_scale": 12.0,
"steps": 60
}
}
config_style = style_configs.get(style, style_configs["realistic"])
image = Image.open(image_path).convert("RGB")
service = IOService()
config = OutpaintConfig(
direction=direction,
pixels=512,
model_name="sd1.5",
prompt=config_style["prompt"],
negative_prompt=config_style["negative"],
guidance_scale=config_style["guidance_scale"],
ddim_steps=config_style["steps"],
seed=42 # 固定种子便于复现
)
result = service.outpaint(image, config)
result.save(output_path)
return result
# 测试不同风格
styles = ["realistic", "artistic", "fantasy"]
for style in styles:
expand_with_style(
image_path="forest.jpg",
output_path=f"forest_{style}.jpg",
direction="right",
style=style
)
4.4 教程四:批量处理大量图片
当需要处理多张图片时,批量处理可以大大提高效率:
4.4.1 批量去除水印
import os
from pathlib import Path
from PIL import Image, ImageDraw
from iopaint.api import IOService
from iopaint.schema import ModelConfig
class BatchProcessor:
"""批量图片处理器"""
def __init__(self, device="cuda"):
self.service = IOService()
self.device = device
def batch_remove_watermark(self, input_dir, output_dir,
watermark_positions, model="lama"):
"""
批量去除水印
参数:
input_dir: 输入文件夹路径
output_dir: 输出文件夹路径
watermark_positions: 水印位置列表
格式: [(x1, y1, w1, h1), (x2, y2, w2, h2), ...]
model: 使用的模型
"""
# 确保输出目录存在
os.makedirs(output_dir, exist_ok=True)
# 获取所有图片文件
input_path = Path(input_dir)
image_files = list(input_path.glob("*.jpg")) + \
list(input_path.glob("*.png")) + \
list(input_path.glob("*.jpeg"))
print(f"找到 {len(image_files)} 张图片")
# 配置模型
config = ModelConfig(
model_name=model,
device=self.device
)
# 处理每张图片
success_count = 0
for i, image_file in enumerate(image_files):
try:
print(f"🔄 处理 {i+1}/{len(image_files)}: {image_file.name}")
# 加载图片
image = Image.open(image_file).convert("RGB")
# 创建遮罩(覆盖所有水印位置)
mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(mask)
for x, y, w, h in watermark_positions:
draw.rectangle([x, y, x+w, y+h], fill=255)
# 执行修复
result = self.service.inpaint(image, mask, config)
# 保存结果
output_file = os.path.join(output_dir, image_file.name)
result.save(output_file)
success_count += 1
print(f" ✅ 已保存: {output_file}")
except Exception as e:
print(f" ❌ 处理失败: {e}")
print(f"\n🎉 批量处理完成!成功: {success_count}/{len(image_files)}")
return success_count
# 使用示例
processor = BatchProcessor(device="cuda")
# 假设所有图片的水印位置相同
watermark_positions = [
(100, 50, 200, 30), # 顶部水印
(100, 100, 150, 20), # 左下水印
]
processor.batch_remove_watermark(
input_dir="images_with_watermark",
output_dir="images_cleaned",
watermark_positions=watermark_positions,
model="lama"
)
4.4.2 批量老照片修复
def batch_restore_photos(input_dir, output_dir, mask_type="auto"):
"""
批量修复老照片
参数:
input_dir: 输入文件夹
output_dir: 输出文件夹
mask_type: 遮罩类型 ("auto", "full")
"""
os.makedirs(output_dir, exist_ok=True)
input_path = Path(input_dir)
image_files = list(input_path.glob("*.jpg")) + \
list(input_path.glob("*.png"))
restorer = OldPhotoRestorer(device="cuda")
results = []
for image_file in image_files:
print(f"\n📷 处理: {image_file.name}")
try:
# 修复照片
result = restorer.restore(
image_path=str(image_file),
output_path=os.path.join(output_dir, image_file.name),
use_auto_mask=(mask_type == "auto"),
model="mat"
)
results.append({
"file": image_file.name,
"status": "success",
"size": result.size
})
except Exception as e:
print(f" ❌ 错误: {e}")
results.append({
"file": image_file.name,
"status": "failed",
"error": str(e)
})
# 打印统计
success = sum(1 for r in results if r["status"] == "success")
print(f"\n========== 统计 ==========")
print(f"总计: {len(results)} 张")
print(f"成功: {success} 张")
print(f"失败: {len(results) - success} 张")
return results
# 使用示例
batch_restore_photos(
input_dir="old_photos",
output_dir="restored_photos",
mask_type="auto"
)
4.4.3 带进度条的批量处理
from tqdm import tqdm
import time
def batch_process_with_progress(input_dir, output_dir, operation="inpaint",
regions=None, model="lama"):
"""
带进度条的批量处理
参数:
input_dir: 输入目录
output_dir: 输出目录
operation: 操作类型 ("inpaint", "outpaint", "remove_bg")
regions: 修复区域
model: 模型名称
"""
os.makedirs(output_dir, exist_ok=True)
input_path = Path(input_dir)
image_files = [f for f in input_path.glob("*.*")
if f.suffix.lower() in ['.jpg', '.png', '.jpeg']]
service = IOService()
config = ModelConfig(model_name=model, device="cuda")
# 使用 tqdm 显示进度
with tqdm(image_files, desc=f"批量{operation}") as pbar:
for image_file in pbar:
# 更新进度条描述
pbar.set_description(f"处理: {image_file.name[:15]}...")
try:
image = Image.open(image_file).convert("RGB")
if operation == "inpaint" and regions:
# 创建遮罩
mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(mask)
for region in regions:
draw.rectangle(region, fill=255)
result = service.inpaint(image, mask, config)
elif operation == "remove_bg":
from iopaint.api import BackgroundRemover
remover = BackgroundRemover(model_name="u2net")
result = remover.remove(image)
else:
continue
result.save(os.path.join(output_dir, image_file.name))
# 模拟处理延迟(实际不需要)
time.sleep(0.1)
except Exception as e:
pbar.write(f"错误 {image_file.name}: {e}")
print(f"\n✅ 批量处理完成!结果保存在: {output_dir}")
# 使用示例
batch_process_with_progress(
input_dir="photos_to_process",
output_dir="processed_photos",
operation="inpaint",
regions=[(100, 100, 200, 200)],
model="lama"
)
五、常见使用场景
5.1 电商场景
场景一:商品图背景处理
def prepare_product_image(image_path, output_path, bg_color=(255, 255, 255)):
"""
处理电商商品图:去除背景,添加纯色背景
适用场景:淘宝、京东、亚马逊等平台商品图
"""
from iopaint.api import BackgroundRemover
# 加载图片
image = Image.open(image_path).convert("RGB")
# 移除背景
remover = BackgroundRemover(model_name="u2net")
no_bg = remover.remove(image)
# 添加纯色背景
result = Image.new("RGB", no_bg.size, bg_color)
result.paste(no_bg, mask=no_bg.split()[3] if no_bg.mode == "RGBA" else None)
result.save(output_path)
return result
# 准备商品图
prepare_product_image("watch.jpg", "watch_clean.png", bg_color=(255, 255, 255))
场景二:修复商品瑕疵
def fix_product_defects(image_path, defect_regions, output_path):
"""
修复商品图片中的瑕疵
defect_regions: 瑕疵区域列表 [(x, y, w, h), ...]
"""
image = Image.open(image_path).convert("RGB")
# 创建遮罩
mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(mask)
for x, y, w, h in defect_regions:
draw.rectangle([x, y, x+w, y+h], fill=255)
# 修复
service = IOService()
config = ModelConfig(model_name="lama", device="cuda")
result = service.inpaint(image, mask, config)
result.save(output_path)
return result
# 修复商品瑕疵
fix_product_defects(
"phone_case.jpg",
[(150, 200, 50, 50)], # 一个瑕疵区域
"phone_case_fixed.jpg"
)
5.2 摄影后期
场景一:移除照片中的游客
def remove_tourists(photo_path, output_path):
"""
从旅游照片中移除游客
技巧:对于游客这种人像,推荐使用较大的画笔涂抹
"""
image = Image.open(photo_path).convert("RGB")
# 手动涂抹游客区域(这里用代码模拟)
mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(mask)
# 假设游客在以下位置(实际使用时用画笔涂抹)
tourist_regions = [
(300, 400, 100, 150), # 游客A
(500, 380, 80, 140), # 游客B
]
for x, y, w, h in tourist_regions:
# 使用椭圆来更贴合人形
draw.ellipse([x, y, x+w, y+h], fill=255)
# 使用 MAT 模型,对人物边缘处理更好
service = IOService()
config = ModelConfig(model_name="mat", device="cuda")
result = service.inpaint(image, mask, config)
result.save(output_path)
return result
场景二:修复闭眼的照片
def fix_closed_eyes(photo_path, face_region, output_path):
"""
修复闭眼的照片
face_region: 人脸区域 (x, y, w, h)
"""
image = Image.open(photo_path).convert("RGB")
# 创建遮罩 - 只覆盖眼睛区域
x, y, w, h = face_region
mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(mask)
# 眼睛通常在脸部上1/3区域
eye_y = y + h // 6
eye_h = h // 5
eye_w = w // 2
# 左眼
left_eye_x = x + w // 4 - eye_w // 2
draw.ellipse([left_eye_x, eye_y, left_eye_x + eye_w, eye_y + eye_h], fill=255)
# 右眼
right_eye_x = x + 3 * w // 4 - eye_w // 2
draw.ellipse([right_eye_x, eye_y, right_eye_x + eye_w, eye_y + eye_h], fill=255)
# 使用 instruct-pix2pix 模型,可以更好地理解指令
service = IOService()
config = ModelConfig(
model_name="instruct-pix2pix",
device="cuda",
prompt="open eyes, natural looking eyes",
guidance_scale=7.5
)
result = service.inpaint(image, mask, config)
result.save(output_path)
return result
5.3 创意设计
场景一:无缝图案生成
def generate_seamless_pattern(base_image_path, output_path):
"""
生成无缝图案
适用于:布料设计、墙纸、背景图等
"""
from iopaint.api import IOService
# 加载基础图案
base = Image.open(base_image_path).convert("RGB")
w, h = base.size
# 创建扩展用的图片(复制并拼接)
# 2x2 拼贴
extended = Image.new("RGB", (w * 2, h * 2))
extended.paste(base, (0, 0))
extended.paste(base, (w, 0))
extended.paste(base, (0, h))
extended.paste(base, (w, h))
service = IOService()
# 向右扩展
config_right = OutpaintConfig(direction="right", pixels=w, model_name="sd1.5")
step1 = service.outpaint(extended, config_right)
# 向下扩展
config_bottom = OutpaintConfig(direction="bottom", pixels=h, model_name="sd1.5")
result = service.outpaint(step1, config_bottom)
# 裁剪回原始尺寸
final = result.crop((0, 0, w, h))
final.save(output_path)
return final
场景二:风格化图像扩展
def artistic_expansion(image_path, output_path, style_prompt):
"""
艺术化图像扩展
使用 AI 生成风格统一的扩展内容
"""
image = Image.open(image_path).convert("RGB")
service = IOService()
# 设置风格化提示词
config = OutpaintConfig(
direction="right",
pixels=512,
model_name="sd1.5",
prompt=style_prompt,
negative_prompt="low quality, blurry, distorted",
guidance_scale=15.0, # 高引导值使风格更明显
ddim_steps=60
)
result = service.outpaint(image, config)
result.save(output_path)
return result
# 示例:生成水彩风格的扩展
artistic_expansion(
"flower.jpg",
"flower_watercolor.jpg",
style_prompt="watercolor painting style, soft brush strokes, artistic interpretation"
)
5.4 文档处理
场景:修复扫描文档
def enhance_scanned_document(image_path, output_path):
"""
增强扫描文档
- 去除污渍
- 修复缺失文字
- 提高清晰度
"""
image = Image.open(image_path).convert("RGB")
# 1. 预处理 - 提高对比度和清晰度
enhanced = ImageEnhance.Contrast(image).enhance(2.0)
enhanced = ImageEnhance.Sharpness(enhanced).enhance(2.0)
# 2. 检测文档问题区域
# 通常文档的边缘和折痕会有问题
# 转换为灰度检测
gray = np.array(enhanced.convert("L"))
# 找出过暗或过亮的区域
dark_mask = gray < 50
bright_mask = gray > 200
# 合并问题区域
problem_mask = np.logical_or(dark_mask, bright_mask).astype(np.uint8) * 255
# 形态学处理
kernel = np.ones((3, 3), np.uint8)
problem_mask = cv2.morphologyEx(problem_mask, cv2.MORPH_CLOSE, kernel)
mask = Image.fromarray(problem_mask)
# 3. 修复
service = IOService()
config = ModelConfig(model_name="lama", device="cuda")
result = service.inpaint(enhanced, mask, config)
# 4. 二值化处理(如果需要)
# result_bw = result.convert("L").point(lambda x: 0 if x < 128 else 255)
result.save(output_path)
return result
六、技巧与最佳实践
6.1 选择合适的模型
选择指南:
┌─────────────────────────────────────────────────────────┐
│ 任务类型 │ 推荐模型 │ 理由 │
├─────────────────────────────────────────────────────────┤
│ 快速日常修复 │ LaMa │ 速度快,效果稳定 │
│ 高清细节保留 │ MAT │ 边缘和纹理处理更好 │
│ 大面积创意生成 │ SD系列 │ 生成能力强 │
│ 背景移除 │ U2Net │ 专为抠图设计 │
│ 文本引导编辑 │ Instruct │ 理解自然语言指令 │
│ 图像扩展 │ SD1.5 │ 扩展效果好 │
└─────────────────────────────────────────────────────────┘
6.2 遮罩绘制技巧
遮罩大小选择
# 遮罩绘制原则
"""
1. 不要只覆盖明显的目标区域
2. 周围留出一些边距(10-20像素)
3. 边缘要平滑,不要有锯齿
正确示例:
┌────────────────────┐
│ ##### │ ← 目标区域
│ ##### │
│ ####### │ ← 周围留有余量
│ ##### │
│ ##### │
└────────────────────┘
错误示例:
┌────────────────────┐
│ ### │ ← 太小,可能留下痕迹
│ ### │
└────────────────────┘
硬边缘 vs 软边缘
# 硬边缘遮罩(适合规则形状)
hard_mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(hard_mask)
draw.rectangle([100, 100, 200, 200], fill=255)
# 软边缘遮罩(适合不规则形状,效果更自然)
from PIL import ImageFilter
def create_soft_mask(image_size, center, radius):
"""创建渐变边缘的遮罩"""
# 创建一个圆形渐变遮罩
mask = Image.new("L", image_size, 0)
# 绘制多个同心圆,从内到外逐渐变淡
for i in range(radius, 0, -1):
alpha = int(255 * (i / radius))
draw = ImageDraw.Draw(mask)
draw.ellipse(
[center[0]-i, center[1]-i, center[0]+i, center[1]+i],
fill=alpha
)
# 高斯模糊使边缘更自然
mask = mask.filter(ImageFilter.GaussianBlur(radius=5))
return mask
soft_mask = create_soft_mask(image.size, (150, 150), 50)
6.3 提示词工程
有效提示词
# ✅ 好的提示词示例
good_prompts = [
# 具体的描述
"a wooden table with natural grain texture",
# 包含场景背景
"the same white wall, natural lighting, smooth surface",
# 指定风格
"realistic photo, high detail, 8k quality",
# 包含负面排除
# (在实际使用时放入 negative_prompt)
# "blurry, watermark, text, distorted"
]
# ❌ 不好的提示词示例
bad_prompts = [
# 太模糊
"something good",
# 自相矛盾
"day and night scene",
# 包含不需要的元素
"include people" # 当你想去除人时
]
提示词模板
def build_inpaint_prompt(scene_description, style="realistic", **kwargs):
"""
构建修复提示词的辅助函数
参数:
scene_description: 场景描述
style: 风格 ("realistic", "artistic", "vintage")
**kwargs: 其他可选参数
"""
base_prompts = {
"realistic": "photorealistic, high detail, natural lighting, 8k",
"artistic": "artistic interpretation, professional photography, studio lighting",
"vintage": "vintage style, warm tones, nostalgic atmosphere"
}
prompt = f"{scene_description}, {base_prompts.get(style, '')}"
# 添加额外参数
if kwargs.get("quality"):
prompt += f", {kwargs['quality']} quality"
if kwargs.get("lighting"):
prompt += f", {kwargs['lighting']} lighting"
return prompt
# 使用示例
prompt = build_inpaint_prompt(
scene_description="seamless continuation of the blue sky",
style="realistic",
quality="ultra high",
lighting="natural"
)
print(prompt)
# 输出: seamless continuation of the blue sky, photorealistic, high detail,
# natural lighting, 8k, ultra high quality, natural lighting
6.4 参数调优指南
"""
参数调优指南
1. guidance_scale(引导强度)
- 低值 (1-5): 更多随机性,可能产生意外结果
- 中值 (7-9): 平衡创意和稳定性,推荐起始值
- 高值 (10-15): 严格遵循提示词,可能牺牲自然度
2. ddim_steps(采样步数)
- 少步数 (20-30): 速度快,可能有噪点
- 中步数 (40-50): 平衡速度和质量的推荐值
- 多步数 (60-100): 细节更好,速度慢
3. hd_strategy(高清策略)
- ORIGINAL: 保持原始尺寸
- CROPPED: 裁剪后处理再拼接
- RESIZE: 缩放处理再放大
4. l2_zero_thresh(MAT模型专用)
- 控制修复区域的"干净"程度
- 低值 (0.3-0.5): 保留更多原始信息
- 高值 (0.7-1.0): 生成更干净的结果
"""
# 针对不同场景的参数推荐
scenario_params = {
# 日常照片修复
"casual_photo": {
"model": "lama",
"guidance_scale": 7.5,
"ddim_steps": 30
},
# 高清照片精细修复
"hd_photo_detail": {
"model": "mat",
"guidance_scale": 7.5,
"ddim_steps": 50,
"hd_strategy": "ORIGINAL"
},
# 创意扩展
"creative_outpaint": {
"model": "sd1.5",
"guidance_scale": 12.0,
"ddim_steps": 60
},
# 文字区域修复
"text_recovery": {
"model": "lama",
"guidance_scale": 5.0, # 较低值保持文字可读性
"ddim_steps": 40
},
# 大面积缺失
"large_missing": {
"model": "sd1.5",
"guidance_scale": 10.0,
"ddim_steps": 80, # 更多步数处理大面积
"prompt": "natural scene continuation"
}
}
6.5 性能优化技巧
加速处理
# 性能优化技巧
# 1. 减小输入图片尺寸
def resize_for_processing(image, max_dimension=1024):
"""将图片缩小到合适尺寸,加快处理速度"""
if max(image.size) > max_dimension:
ratio = max_dimension / max(image.size)
new_size = (int(image.size[0] * ratio), int(image.size[1] * ratio))
return image.resize(new_size, Image.LANCZOS)
return image
# 2. 批量处理时复用模型
class OptimizedProcessor:
def __init__(self, model_name="lama"):
self.service = IOService()
self.config = ModelConfig(model_name=model_name, device="cuda")
self._is_model_loaded = False
def process(self, image, mask):
"""处理单张图片"""
if not self._is_model_loaded:
# 模型只在第一次使用时加载
self.service.load_model(self.config)
self._is_model_loaded = True
return self.service.inpaint(image, mask, self.config)
# 3. 使用半精度加速(如果有支持)
config_fp16 = ModelConfig(
model_name="lama",
device="cuda",
dtype="float16" # 使用半精度,减少显存使用
)
显存不足时的处理
# 显存不足解决方案
# 方案1:减小批处理大小
config_small_batch = ModelConfig(
model_name="lama",
device="cuda",
# 使用更小的处理块
hd_strategy="CROPPED",
hd_strategy_crop_size=256 # 减小裁剪大小
)
# 方案2:使用 CPU(作为备选)
config_cpu = ModelConfig(
model_name="lama",
device="cpu" # 虽然慢,但不会显存不足
)
# 方案3:选择更轻量的模型
lightweight_models = ["lama"] # LaMa 相对轻量
# 方案4:分块处理大图
def process_large_image_in_tiles(image_path, mask_path, output_path,
tile_size=512, overlap=64):
"""
分块处理大图,避免显存不足
参数:
tile_size: 每块的大小
overlap: 块之间的重叠(用于平滑拼接)
"""
image = Image.open(image_path)
mask = Image.open(mask_path)
w, h = image.size
service = IOService()
config = ModelConfig(model_name="lama", device="cuda")
# 创建结果图像
result = Image.new("RGB", (w, h))
count_map = Image.new("L", (w, h), 0) # 计数图,用于平均
step = tile_size - overlap
for y in range(0, h, step):
for x in range(0, w, step):
# 裁剪当前块
tile = image.crop((x, y, min(x+tile_size, w), min(y+tile_size, h)))
tile_mask = mask.crop((x, y, min(x+tile_size, w), min(y+tile_size, h)))
# 处理当前块
tile_result = service.inpaint(tile, tile_mask, config)
# 粘贴回结果
result.paste(tile_result, (x, y))
result.save(output_path)
return result
七、常见问题解答
7.1 安装问题
Q: 安装时报错 torch.cuda.is_available() = False
# 解决方案:确认 CUDA 安装
# 1. 检查 NVIDIA 驱动
nvidia-smi
# 2. 安装 CUDA 版本的 PyTorch
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
# 3. 验证安装
python -c "import torch; print(torch.cuda.is_available())"
Q: 提示 No module named 'iopaint'
# 确保在正确的虚拟环境中安装
# 检查当前 Python
which python
# 重新安装
pip install iopaint --force-reinstall
# 或者如果使用开发模式安装
cd IOPaint
pip install -e .
7.2 运行问题
Q: Web 界面无法访问
# 检查 IOPaint 是否正在运行
ps aux | grep iopaint
# 检查端口占用
lsof -i :8080
# 尝试使用其他端口
iopaint run --port 8888
# 检查防火墙设置
# Linux:
sudo ufw allow 8080
# Windows:
# 在防火墙设置中允许 python.exe
Q: 模型下载失败
# 手动下载模型
# 1. 创建模型目录
mkdir -p ~/.cache/torch/hub/models
# 2. 从 HuggingFace 下载
# 访问 https://huggingface.co/<model-name>
# 3. 将模型文件放到正确位置
mv downloaded_model.py ~/.cache/torch/hub/models/
# 4. 或者使用镜像
export HF_ENDPOINT=https://hf-mirror.com
7.3 使用问题
Q: 修复效果不理想,有明显痕迹
可能原因和解决方案:
1. 遮罩边缘不平滑
→ 使用软边缘遮罩,或扩大遮罩范围
2. 修复区域太大
→ 分多次小区域修复
3. 模型选择不当
→ 尝试不同模型(LaMa/MAT/SD)
4. 参数设置不当
→ 调整 guidance_scale 或 steps
5. 提示词不准确
→ 使用更具体、简洁的描述
Q: 显存不足(OOM)
# 解决方案
# 1. 减小图片尺寸
image = image.resize((1024, 1024), Image.LANCZOS)
# 2. 使用更小的模型
config = ModelConfig(model_name="lama") # 比 MAT 轻量
# 3. 降低高清策略的裁剪大小
config.hd_strategy_crop_size = 256
# 4. 清空 GPU 缓存
import torch
torch.cuda.empty_cache()
Q: 生成的内容不自然
优化建议:
1. 检查原图和生成内容的风格一致性
2. 增加引导强度(guidance_scale)
3. 使用更多采样步数
4. 优化提示词:
- 添加场景描述(光线、背景)
- 使用负面提示词排除不需要的元素
5. 尝试使用 MAT 模型(边缘处理更好)
7.4 高级问题
Q: 如何集成到自己的应用?
# 作为 Python 库使用
from iopaint.api import IOService
from iopaint.schema import ModelConfig
# 初始化
service = IOService()
# 处理单张图片
def process_image(image_path, mask_path, output_path):
image = Image.open(image_path).convert("RGB")
mask = Image.open(mask_path).convert("L")
config = ModelConfig(model_name="lama", device="cuda")
result = service.inpaint(image, mask, config)
result.save(output_path)
# 作为 REST API 使用
# 启动服务器
iopaint run --api
# 然后通过 HTTP 请求调用
import requests
response = requests.post("http://localhost:8080/inpaint", files={
"image": open("input.jpg", "rb"),
"mask": open("mask.png", "rb")
}, data={
"model": "lama"
})
with open("output.jpg", "wb") as f:
f.write(response.content)
Q: 如何训练自己的模型?
# IOPaint 支持自定义模型训练(高级功能)
# 1. 准备训练数据
"""
训练数据目录结构:
dataset/
├── images/
│ ├── image1.jpg
│ ├── image2.jpg
│ └── ...
└── masks/
├── mask1.png
├── mask2.png
└── ...
"""
# 2. 配置文件
train_config = {
"model_type": "lama", # 或 mat, sd
"dataset_path": "./dataset",
"batch_size": 4,
"learning_rate": 0.0001,
"epochs": 100,
"output_dir": "./trained_model"
}
# 3. 开始训练(具体命令参考项目文档)
# python -m iopaint.train --config train_config.yaml
八、总结与相关资源
8.1 核心要点回顾
┌─────────────────────────────────────────────────────────────┐
│ IOPaint 使用要点 │
├─────────────────────────────────────────────────────────────┤
│ 1. 安装简单:pip install iopaint │
│ 2. 界面友好:Web界面直观易用 │
│ 3. 模型丰富:40+模型满足各种场景 │
│ 4. 隐私安全:本地处理,图片不上传 │
│ 5. 扩展性强:支持 Python API 和自定义模型 │
└─────────────────────────────────────────────────────────────┘
推荐使用场景:
✓ 去除照片中的不需要元素
✓ 修复老照片
✓ 智能扩图
✓ 背景移除
✓ 商品图处理
✓ 创意设计
8.2 相关 AI 项目推荐
| 项目名称 | 类型 | 特点 |
|---|---|---|
| Stable Diffusion | 文生图 | 最流行的开源图像生成模型 |
| ControlNet | 条件控制 | 通过边缘、姿态等控制生成 |
| Segment Anything | 分割工具 | 强大的图像分割模型 |
| CLIP | 多模态 | 图文理解基础模型 |
| Real-ESRGAN | 超分辨率 | 图片清晰度提升 |
| GFPGAN | 人脸修复 | 专业人像修复工具 |
| Denoise Diffusion | 去噪模型 | 图像去噪处理 |
| Lama Cleaner | 图像修复 | 轻量级修复工具 |
8.3 进阶学习资源
# 推荐学习路径
learning_path = [
# 基础阶段
"1. 熟悉 IOPaint Web 界面操作",
"2. 学习基本的图像修复流程",
"3. 了解不同模型的特点",
# 进阶阶段
"4. 学习 Python API 编程",
"5. 掌握遮罩绘制技巧",
"6. 学习提示词工程",
"7. 参数调优实践",
# 高级阶段
"8. 批量处理自动化",
"9. 自定义模型训练",
"10. 应用集成开发"
]
for i, step in enumerate(learning_path):
print(f"{i+1}. {step}")
8.4 项目链接
IOPaint 官方资源:
📦 GitHub 仓库:https://github.com/Sanster/IOPaint
📖 项目文档:https://github.com/Sanster/IOPaint#readme
💬 问题反馈:https://github.com/Sanster/IOPaint/issues
🔧 模型下载:https://huggingface.co/models
8.5 写在最后
IOPaint 是一个非常实用的开源图像修复工具,它将复杂的 AI 模型封装成了简单易用的界面和 API。无论你是设计师、摄影师、电商运营,还是普通的图片爱好者,都能从中受益。
核心优势总结:
免费开源 → 无使用成本,可自由定制
本地处理 → 保护隐私,安全可靠
模型丰富 → 40+ 模型覆盖各种场景
易于集成 → Python API 方便开发
社区活跃 → 持续更新,问题能得到响应
开始使用 IOPaint 的最佳方式:
# 最简单的方式
pip install iopaint
iopaint run
# 然后打开浏览器访问 http://localhost:8080
现在就动手试试吧!无论是修复一张老照片,还是批量处理商品图,IOPaint 都能帮你轻松完成。
祝你玩得开心!如果觉得有用,欢迎给项目点个 Star ⭐
评论区