← 返回
未分类

China Id Photo

生成中国标准证件照。Use when the user needs to create an ID photo, passport photo, visa photo, or any standard photo with specific size and background color. Supports...
生成中国标准证件照。Use when the user needs to create an ID photo, passport photo, visa photo, or any standard photo with specific size and background color. Supports...
tobewin tobewin 来源
未分类 clawhub v1.2.1 1 版本 100000 Key: 无需
★ 0
Stars
📥 636
下载
💾 17
安装
1
版本
#latest

概述

中国证件照生成 China ID Photo

将个人照片转换为符合中国标准的证件照,支持多种尺寸和背景颜色。

功能特点

  • 🎨 支持白/蓝/红三种标准背景色
  • 📐 支持1寸、2寸、护照等标准尺寸
  • 🖼️ 输出JPEG(默认)或PNG格式
  • 🔒 完全本地处理,不上传任何服务器

触发时机

  • "帮我做一张证件照"
  • "把这张照片转成1寸证件照"
  • "我需要蓝色背景的2寸照片"
  • "生成护照照片,白色背景"
  • "这张照片转成证件照,要红色背景"
  • "帮我制作身份证照片"

Step 0:环境检查与依赖安装

# 检查 python3
if ! command -v python3 &> /dev/null; then
  echo "❌ 需要 python3"
  echo "  macOS:  brew install python3"
  echo "  Ubuntu: sudo apt install python3"
  echo "  Windows: 从 python.org 下载安装"
  exit 1
fi

# 检查并安装依赖
echo "📦 检查依赖..."
pip install rembg pillow opencv-python-headless -q 2>/dev/null || {
  echo "❌ 依赖安装失败,请手动执行:"
  echo "  pip install rembg pillow opencv-python-headless"
  exit 1
}

echo "✅ 环境检查通过"

Step 1:识别用户需求

用户提供照片路径 → 识别参数:

尺寸(用户指定或默认1寸):
  "1寸" / "一寸" / "小一寸"     → 295×413 像素
  "2寸" / "二寸"                → 413×579 像素
  "小二寸" / "护照" / "passport" → 390×567 像素
  "大一寸" / "签证" / "visa"     → 390×567 像素
  "身份证" / "id card"          → 358×441 像素
  未指定                        → 默认1寸(295×413)

背景色(用户指定或默认白色):
  "白色" / "白底" / "white"     → #FFFFFF
  "蓝色" / "蓝底" / "blue"      → #438EDB(标准证件照蓝)
  "红色" / "红底" / "red"       → #FF0000
  未指定                        → 默认白色

输出格式:
  "PNG" / "png" / "透明"        → PNG格式
  未指定                        → 默认JPEG格式

Step 2:生成证件照

# 设置参数(根据用户需求调整)
INPUT_IMAGE="/path/to/user/photo.jpg"
SIZE="1"           # 尺寸:1/2/passport/id_card
BG_COLOR="white"   # 背景色:white/blue/red
OUTPUT_FORMAT="jpg" # 输出格式:jpg/png

# 创建输出目录
OUTPUT_DIR="${OPENCLAW_WORKSPACE:-$PWD}/id_photo_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"

# 执行Python脚本处理图片
python3 - "$INPUT_IMAGE" "$OUTPUT_DIR" "$SIZE" "$BG_COLOR" "$OUTPUT_FORMAT" << 'PYEOF'
import sys
import os
from rembg import remove
from PIL import Image, ImageFilter
import cv2
import numpy as np

# 从命令行参数获取配置
input_path = sys.argv[1]
output_dir = sys.argv[2]
size_type = sys.argv[3]
bg_color_name = sys.argv[4]
output_format = sys.argv[5]

# 标准尺寸映射(像素,300DPI)
SIZES = {
    '1': (295, 413),        # 1寸
    '2': (413, 579),        # 2寸
    'passport': (390, 567), # 护照/小二寸
    'id_card': (358, 441),  # 身份证
}

# 背景色映射(RGB)- 中国证件照标准色值
BG_COLORS = {
    'white': (255, 255, 255),   # 白色:身份证、护照、签证
    'blue': (67, 142, 219),     # 蓝色:毕业证、工作证
    'red': (255, 0, 0),         # 红色:结婚证、党员证
}

def detect_face(img_array):
    """使用OpenCV检测人脸,返回包含头发的头部边界框"""
    face_cascade = cv2.CascadeClassifier(
        cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
    )
    
    if len(img_array.shape) == 3:
        gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
    else:
        gray = img_array
    
    faces = face_cascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30)
    )
    
    if len(faces) > 0:
        # 返回最大的人脸
        areas = [w * h for (x, y, w, h) in faces]
        max_idx = areas.index(max(areas))
        fx, fy, fw, fh = faces[max_idx]
        
        # 扩展边界框以包含头发
        # 向上扩展约40%(头发区域)
        # 向下扩展约10%(下巴下方)
        # 向左右各扩展约10%
        expand_top = int(fh * 0.4)
        expand_bottom = int(fh * 0.1)
        expand_side = int(fw * 0.1)
        
        # 计算扩展后的边界框(确保不超出图片边界)
        img_h, img_w = gray.shape
        new_x = max(0, fx - expand_side)
        new_y = max(0, fy - expand_top)
        new_w = min(fw + expand_side * 2, img_w - new_x)
        new_h = min(fh + expand_top + expand_bottom, img_h - new_y)
        
        return (new_x, new_y, new_w, new_h)
    
    return None

def refine_mask(mask, radius=2):
    """优化抠图边缘,去除锯齿"""
    # 转换为numpy数组
    mask_np = np.array(mask)
    
    # 轻微模糊边缘
    mask_np = cv2.GaussianBlur(mask_np, (radius*2+1, radius*2+1), 0)
    
    # 二值化
    _, mask_np = cv2.threshold(mask_np, 128, 255, cv2.THRESH_BINARY)
    
    return Image.fromarray(mask_np)

def crop_face_centered(img, target_size, face_bbox=None):
    """根据头部位置进行智能裁剪,确保头顶留白符合证件照标准
    
    标准要求:
    - 头顶到照片上边沿:约10%照片高度
    - 头部高度:约65%照片高度
    - 头部水平居中
    """
    target_w, target_h = target_size
    target_ratio = target_w / target_h
    img_w, img_h = img.size
    
    if face_bbox is not None:
        fx, fy, fw, fh = face_bbox
        
        # 计算头部中心(水平位置)
        head_cx = fx + fw // 2
        
        # 根据中国证件照标准计算裁剪区域
        # 头部高度应占照片高度的65%
        # 头顶留白占照片高度的10%
        
        # 假设face_bbox已经是扩展后的头部区域
        # 头部高度 fh 对应照片高度的 65%
        target_area_h = int(fh / 0.65)
        target_area_w = int(target_area_h * target_ratio)
        
        # 确保不超出图片
        target_area_w = min(target_area_w, img_w)
        target_area_h = min(target_area_h, img_h)
        
        # 水平居中
        crop_x = head_cx - target_area_w // 2
        
        # 垂直位置:头顶留10%空白
        # face_bbox的y坐标是头顶位置
        # 头顶到裁剪区域顶部的距离 = 照片高度 * 10%
        head_top_offset = int(target_area_h * 0.10)
        crop_y = fy - head_top_offset
        
        # 边界调整
        crop_x = max(0, min(crop_x, img_w - target_area_w))
        crop_y = max(0, min(crop_y, img_h - target_area_h))
        
        img = img.crop((crop_x, crop_y, crop_x + target_area_w, crop_y + target_area_h))
    else:
        # 没有检测到人脸,使用改进的居中裁剪
        img_ratio = img_w / img_h
        if img_ratio > target_ratio:
            new_w = int(img_h * target_ratio)
            left = (img_w - new_w) // 2
            img = img.crop((left, 0, left + new_w, img_h))
        else:
            new_h = int(img_w / target_ratio)
            top = int((img_h - new_h) * 0.15)  # 上方留15%空白
            img = img.crop((0, top, img_w, top + new_h))
    
    # 缩放到目标尺寸(使用高质量缩放)
    return img.resize(target_size, Image.LANCZOS)

def process_image(input_path, output_dir, size_type, bg_color_name, output_format):
    print(f"📸 正在处理图片...")
    
    if not os.path.exists(input_path):
        print(f"❌ 文件不存在: {input_path}")
        sys.exit(1)
    
    # 读取原图
    input_img = Image.open(input_path).convert('RGB')
    orig_size = input_img.size
    print(f"   原图尺寸: {orig_size}")
    
    # 检测人脸位置(在抠图前检测)
    print("👤 检测人脸...")
    img_array = np.array(input_img)
    face_bbox = detect_face(img_array)
    
    if face_bbox is not None:
        fx, fy, fw, fh = face_bbox
        print(f"   检测到人脸: 位置({fx},{fy}) 大小({fw}x{fh})")
    else:
        print("   ⚠️ 未检测到人脸,将使用智能居中裁剪")
    
    # 抠图(移除背景)
    print("✂️ 正在抠图(可能需要几秒)...")
    output_img = remove(input_img)
    
    # 获取目标尺寸
    if size_type in SIZES:
        target_size = SIZES[size_type]
        size_name = {'1': '1寸', '2': '2寸', 'passport': '护照', 'id_card': '身份证'}[size_type]
    else:
        target_size = (295, 413)
        size_name = '1寸(默认)'
    
    print(f"📐 目标尺寸: {size_name} {target_size[0]}x{target_size[1]} 像素")
    
    # 获取背景色
    bg_color = BG_COLORS.get(bg_color_name, BG_COLORS['white'])
    print(f"🎨 背景色: {bg_color_name} RGB{bg_color}")
    
    # 提取并优化alpha通道(抠图边缘)
    if output_img.mode != 'RGBA':
        print("❌ 抠图失败,未生成透明通道")
        sys.exit(1)
    
    r, g, b, a = output_img.split()
    print("🔧 优化抠图边缘...")
    a_refined = refine_mask(a, radius=2)
    
    # 创建纯色背景
    bg = Image.new('RGB', output_img.size, bg_color)
    
    # 将抠图结果粘贴到背景上(使用优化后的mask)
    person_rgb = Image.merge('RGB', (r, g, b))
    bg.paste(person_rgb, mask=a_refined)
    
    # 智能裁剪(根据人脸位置)
    print("✂️ 裁剪到目标尺寸...")
    result = crop_face_centered(bg, target_size, face_bbox)
    
    # 验证输出尺寸
    if result.size != target_size:
        print(f"⚠️ 尺寸调整: {result.size} → {target_size}")
        result = result.resize(target_size, Image.LANCZOS)
    
    # 保存
    output_ext = 'png' if output_format == 'png' else 'jpg'
    output_path = os.path.join(output_dir, f'id_photo_{size_type}_{bg_color_name}.{output_ext}')
    
    if output_ext == 'png':
        result.save(output_path, 'PNG')
    else:
        result.save(output_path, 'JPEG', quality=95, subsampling=0)
    
    file_size = os.path.getsize(output_path)
    print(f"✅ 证件照已生成: {output_path}")
    print(f"   最终尺寸: {result.size[0]}x{result.size[1]} 像素")
    print(f"   文件大小: {file_size / 1024:.1f} KB")
    
    return output_path

try:
    result = process_image(input_path, output_dir, size_type, bg_color_name, output_format)
    print("\n🎉 处理完成!")
except Exception as e:
    print(f"\n❌ 处理失败: {e}")
    import traceback
    traceback.print_exc()
    sys.exit(1)
PYEOF

设置环境变量并执行

export INPUT_IMAGE="/path/to/user/photo.jpg"
export OUTPUT_DIR="${OPENCLAW_WORKSPACE:-$PWD}/id_photo_$(date +%Y%m%d_%H%M%S)"
export SIZE="1"          # 1/2/passport/id_card
export BG_COLOR="white"  # white/blue/red
export OUTPUT_FORMAT="jpg"  # jpg/png

# 执行上面的python脚本

Step 3:输出结果

证件照生成完成后:

✅ 证件照已生成!

📐 尺寸:1寸(295×413像素,2.5×3.5厘米)
🎨 背景:白色
📁 格式:JPEG
📍 位置:/path/to/id_photo_xxx/id_photo_1_white.jpg

可直接用于:
- 简历、报名表
- 各类证件申请
- 在线提交

常用尺寸速查

名称像素厘米常用场景
----------------------------
1寸295×4132.5×3.5简历、报名表
2寸413×5793.5×5.0毕业证、资格证
护照/小二寸390×5673.3×4.8护照、签证
身份证358×4412.6×3.2身份证办理

错误处理

文件不存在           → 提示用户确认照片路径
格式不支持           → 提示支持的格式:JPG, PNG, WEBP
依赖安装失败         → 提示手动安装:pip install rembg pillow
内存不足             → 建议压缩原图后再试
抠图效果不佳         → 建议使用背景简洁的正面照

注意事项

  • 首次运行需下载rembg模型(约170MB),请保持网络连接
  • 建议使用正面免冠照片,背景简洁效果更佳
  • 原图分辨率建议 >= 500×500 像素
  • 处理时间约2-10秒(取决于CPU性能)
  • 所有处理完全在本地进行,不会上传任何数据

版本历史

共 1 个版本

  • v1.2.1 当前
    2026-03-30 17:19 安全 安全

安全检测

腾讯云安全 (Keen)

安全,无风险
查看报告

腾讯云安全 (Sanbu)

安全,无风险
查看报告

🔗 相关推荐

design-media

UI/UX Pro Max

xobi667
提供 UI/UX 设计智能与实现指导,帮助打造精美界面。适用于 UI 设计、UX 流程、信息架构、视觉风格、设计系统/标记、组件规格、文案/微文案、无障碍及前端 UI(HTML/CSS/JS、React、Next.js、Vue、Svelte
★ 216 📥 47,229
office-efficiency

Pptx Generator

tobewin
专业PPT生成器。Use when user wants to create editable PowerPoint presentations with professional layouts, multiple styles, and
★ 15 📥 14,692
design-media

Nano Banana Pro

steipete
使用 Nano Banana Pro (Gemini 3 Pro Image) 生成或编辑图像。支持文生图、图生图及 1K/2K/4K 分辨率,适用于图像创建、修改及编辑请求,使用 --input-image 指定输入图像。
★ 429 📥 116,698