批量转换图片为线稿的脚本

wen 实用脚本 2

本文目录导读:

批量转换图片为线稿的脚本

  1. 使用方法
  2. 功能特点
import cv2
import numpy as np
import os
import argparse
from pathlib import Path
def image_to_line_art(image_path, output_path, method='canny', 
                      blur_ksize=5, threshold1=50, threshold2=150,
                      invert=True, remove_noise=True):
    """
    将单张图片转换为线稿
    参数:
        image_path: 输入图片路径
        output_path: 输出图片路径
        method: 线稿生成方法 ('canny', 'sobel', 'laplacian', 'adaptive')
        blur_ksize: 高斯模糊核大小(奇数)
        threshold1: Canny边缘检测的低阈值
        threshold2: Canny边缘检测的高阈值
        invert: 是否反转颜色(白底黑线)
        remove_noise: 是否去除小噪点
    """
    # 读取图片
    img = cv2.imread(str(image_path))
    if img is None:
        print(f"错误: 无法读取图片 {image_path}")
        return False
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 高斯模糊降噪
    if blur_ksize % 2 == 0:
        blur_ksize += 1  # 确保是奇数
    blurred = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 0)
    # 边缘检测
    if method == 'canny':
        edges = cv2.Canny(blurred, threshold1, threshold2)
    elif method == 'sobel':
        sobelx = cv2.Sobel(blurred, cv2.CV_64F, 1, 0, ksize=3)
        sobely = cv2.Sobel(blurred, cv2.CV_64F, 0, 1, ksize=3)
        edges = cv2.magnitude(sobelx, sobely)
        edges = np.uint8(np.clip(edges, 0, 255))
        _, edges = cv2.threshold(edges, threshold1, 255, cv2.THRESH_BINARY)
    elif method == 'laplacian':
        laplacian = cv2.Laplacian(blurred, cv2.CV_64F)
        edges = np.uint8(np.clip(np.abs(laplacian), 0, 255))
        _, edges = cv2.threshold(edges, threshold1, 255, cv2.THRESH_BINARY)
    elif method == 'adaptive':
        edges = cv2.adaptiveThreshold(blurred, 255, 
                                     cv2.ADAPTIVE_THRESH_MEAN_C,
                                     cv2.THRESH_BINARY, 11, 2)
    else:
        print(f"未知方法: {method},使用默认canny")
        edges = cv2.Canny(blurred, threshold1, threshold2)
    # 去除小噪点
    if remove_noise:
        contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, 
                                       cv2.CHAIN_APPROX_SIMPLE)
        min_contour_area = 50
        for contour in contours:
            if cv2.contourArea(contour) < min_contour_area:
                cv2.drawContours(edges, [contour], -1, 0, -1)
    # 反转颜色
    if invert:
        edges = cv2.bitwise_not(edges)
    # 保存结果
    cv2.imwrite(str(output_path), edges)
    return True
def batch_convert(input_dir, output_dir, **kwargs):
    """
    批量转换目录中的图片
    参数:
        input_dir: 输入目录
        output_dir: 输出目录
        **kwargs: 传递给image_to_line_art的参数
    """
    # 支持的图片格式
    supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif'}
    # 创建输出目录
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    # 获取所有图片文件
    input_path = Path(input_dir)
    image_files = [f for f in input_path.iterdir() 
                   if f.suffix.lower() in supported_formats]
    if not image_files:
        print(f"在 {input_dir} 中未找到支持的图片文件")
        return
    # 转换参数
    success_count = 0
    fail_count = 0
    # 常见参数显示
    method = kwargs.get('method', 'canny')
    threshold1 = kwargs.get('threshold1', 50)
    threshold2 = kwargs.get('threshold2', 150)
    invert = kwargs.get('invert', True)
    print(f"使用方法: {method}, 阈值: {threshold1}/{threshold2}, 反转: {invert}")
    for img_file in image_files:
        output_file = Path(output_dir) / f"{img_file.stem}_line{img_file.suffix}"
        print(f"处理: {img_file.name} -> {output_file.name}")
        success = image_to_line_art(img_file, output_file, **kwargs)
        if success:
            success_count += 1
        else:
            fail_count += 1
    print(f"\n处理完成! 成功: {success_count}, 失败: {fail_count}")
def main():
    parser = argparse.ArgumentParser(description='批量转换图片为线稿')
    parser.add_argument('input_dir', help='输入图片目录')
    parser.add_argument('output_dir', help='输出线稿目录')
    parser.add_argument('--method', choices=['canny', 'sobel', 'laplacian', 'adaptive'],
                       default='canny', help='线稿生成方法 (默认: canny)')
    parser.add_argument('--blur', type=int, default=5, 
                       help='高斯模糊核大小 (默认: 5)')
    parser.add_argument('--threshold1', type=int, default=50,
                       help='边缘检测低阈值 (默认: 50)')
    parser.add_argument('--threshold2', type=int, default=150,
                       help='边缘检测高阈值 (默认: 150)')
    parser.add_argument('--no-invert', action='store_true',
                       help='不反转颜色 (默认反转,产生白底黑线)')
    parser.add_argument('--keep-noise', action='store_true',
                       help='保留小噪点 (默认去除)')
    args = parser.parse_args()
    batch_convert(
        args.input_dir,
        args.output_dir,
        method=args.method,
        blur_ksize=args.blur,
        threshold1=args.threshold1,
        threshold2=args.threshold2,
        invert=not args.no_invert,
        remove_noise=not args.keep_noise
    )
if __name__ == '__main__':
    main()

使用方法

安装依赖

pip install opencv-python numpy

基本使用

# 将input文件夹中的图片转换为线稿,输出到output文件夹
python line_art_converter.py input_folder output_folder

高级用法

# 使用自适应阈值方法,调整模糊和阈值
python line_art_converter.py input output --method adaptive --blur 3
# 使用Sobel方法,不反转颜色(黑底白线)
python line_art_converter.py input output --method sobel --no-invert
# 精细调整Canny阈值
python line_art_converter.py input output --method canny --threshold1 30 --threshold2 100
# 保留噪点
python line_art_converter.py input output --keep-noise

功能特点

  • 四种线稿方法:

    • canny: 经典Canny边缘检测(默认)
    • sobel: Sobel梯度边缘检测
    • laplacian: 拉普拉斯算子边缘检测
    • adaptive: 自适应阈值(适合光照不均的图片)
  • 参数调节:

    • --blur: 模糊程度,值越大线条越粗
    • --threshold1/2: 边缘检测灵敏度
  • 输出控制:

    • 默认白底黑线(反转)
    • 可选黑底白线(--no-invert
    • 自动去除小噪点(可选保留)

脚本会自动处理目录中的所有常见图片格式(jpg、png、bmp、tiff),并在输出文件名后添加_line后缀。

抱歉,评论功能暂时关闭!