Line Art Extractor

Polar Sponsor
爱发电 赞助
.NET 9.0

从任意图片中提取线稿/轮廓图。支持多种方法(Canny边缘检测、素描效果、灰度反色模糊混合、中值滤波+边缘检测),可根据图片类型(照片/插画/动漫/建筑图等)自动推荐最佳方案,也支持批量处理。输出白色背景黑色线稿的高清PNG图片。触发关键词:提取线稿、图片转线稿、线稿提取、图片转轮廓、提取轮廓、照片转线稿、提取线条、图片变线稿、素描提取、轮廓提取、line

Line Art Extractor Skill

功能概述

Line Art Extractor Skill是一项面向实际任务的技能,主要用于从任意图片中提取线稿/轮廓,输出白底黑线的高清线稿图;手绘临摹参考;

核心要点

  • 将照片/插画转为线稿,方便临摹练习;
  • 二次创作底稿;
  • 从现有作品提取线稿后重新上色;

使用与执行

将建筑效果图转为线稿风格;将真人照片转为漫画线稿底图;提取产品/服装轮廓用于设计;提供 4 种线稿提取方法,各有适用场景:;适用图片类型;canny。

结果检查与注意事项

它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。

Line Art Extractor Skill

从任意图片中提取线稿/轮廓,输出白底黑线的高清线稿图。

适用场景

场景 说明
手绘临摹参考 将照片/插画转为线稿,方便临摹练习
二次创作底稿 从现有作品提取线稿后重新上色
建筑草图 将建筑效果图转为线稿风格
漫画分镜 将真人照片转为漫画线稿底图
设计参考 提取产品/服装轮廓用于设计

方法概览

提供 4 种线稿提取方法,各有适用场景:

方法 适用图片类型 效果特点 速度
canny 所有类型 精准边缘检测,线条干净锐利 快
sketch 真人照片 模拟铅笔素描效果,有明暗层次 快
blend 插画/动漫 灰度反色+模糊混合,保留细节丰富 快
median_edge 建筑/产品/清晰图片 中值去噪后边缘检测,抗噪性强 中等

参数说明

参数 类型 默认值 说明
input_path str 必填 输入图片路径(支持 jpg/png/webp/bmp)
output_path str 自动生成 输出路径,默认 {原名}_lineart.png
method str auto 提取方法:canny/sketch/blend/median_edge/auto
threshold1 int 50 Canny 低阈值(仅 canny/median_edge 方法)
threshold2 int 150 Canny 高阈值(仅 canny/median_edge 方法)
blur_strength int 21 模糊核大小,必须为奇数(仅 blend 方法)
invert bool False 是否反转为黑底白线(默认白底黑线)
batch bool False 是否批量处理(输入目录时自动开启)

Auto 模式自动选择逻辑

当 method="auto" 时,根据图片特征自动推荐最佳方法:

  1. 图片整体对比度高 + 边缘清晰 → canny
  2. 图片含大量肤色/柔和渐变(照片特征) → sketch
  3. 色彩饱和度高/线条密集(插画特征) → blend
  4. 图片有噪点/纹理复杂 → median_edge

如果自动检测不确定,默认使用 blend(适用面最广)。

核心代码实现

完整实现(单文件)

import cv2
import numpy as np
from PIL import Image, ImageFilter, ImageOps
import os
import glob


def analyze_image(img_path):
    """分析图片特征,自动推荐最佳方法"""
    img = cv2.imread(img_path)
    if img is None:
        raise ValueError(f"无法读取图片: {img_path}")
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 计算图像特征
    # 1. 对比度(标准差)
    contrast = np.std(gray)
    # 2. 边缘密度(Canny检测后的非零像素占比)
    edges = cv2.Canny(gray, 30, 100)
    edge_density = np.count_nonzero(edges) / edges.size
    # 3. 色彩饱和度(转换HSV后S通道均值)
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    saturation = np.mean(hsv[:, :, 1])
    # 4. 肤色区域占比(HSV空间检测)
    skin_mask = cv2.inRange(hsv, np.array([0, 30, 60]), np.array([25, 180, 255]))
    skin_ratio = np.count_nonzero(skin_mask) / skin_mask.size
    
    features = {
        'contrast': contrast,
        'edge_density': edge_density,
        'saturation': saturation,
        'skin_ratio': skin_ratio
    }
    
    # 决策逻辑
    if contrast > 60 and edge_density > 0.03:
        return 'canny', features
    elif skin_ratio > 0.15:
        return 'sketch', features
    elif saturation > 40 or edge_density > 0.05:
        return 'blend', features
    else:
        return 'median_edge', features


def extract_lineart_canny(img_path, threshold1=50, threshold2=150):
    """Canny 边缘检测法 — 精准锐利"""
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 高斯模糊降噪
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    
    # Canny 边缘检测
    edges = cv2.Canny(blurred, threshold1, threshold2)
    
    # 白底黑线:反转 Canny 输出
    result = cv2.bitwise_not(edges)
    return result


def extract_lineart_sketch(img_path):
    """素描效果法 — 铅笔素描感"""
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 反转灰度图
    inverted = 255 - gray
    
    # 高斯模糊反转图
    blurred = cv2.GaussianBlur(inverted, (21, 21), 0)
    
    # 颜色减淡混合(模拟铅笔素描)
    sketch = cv2.divide(gray, 255 - blurred, scale=256)
    
    # 二值化让线条更清晰
    _, result = cv2.threshold(sketch, 200, 255, cv2.THRESH_BINARY)
    return result


def extract_lineart_blend(img_path, blur_strength=21):
    """灰度反色模糊混合法 — 保留丰富细节"""
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 反转灰度图
    inverted = 255 - gray
    
    # 对反转图做模糊
    blurred = cv2.GaussianBlur(inverted, (blur_strength, blur_strength), 0)
    
    # 与原图灰度做颜色减淡混合
    blended = cv2.divide(gray, 255 - blurred, scale=256)
    
    # 增强对比度让线条更突出
    result = cv2.convertScaleAbs(blended, alpha=1.5, beta=-30)
    
    # 可选:轻度二值化清理
    _, result = cv2.threshold(result, 180, 255, cv2.THRESH_BINARY)
    return result


def extract_lineart_median_edge(img_path, threshold1=30, threshold2=80):
    """中值滤波+边缘检测法 — 抗噪性强"""
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 中值滤波去除噪点
    denoised = cv2.medianBlur(gray, 5)
    
    # Canny 边缘检测(用较低阈值保留更多细节)
    edges = cv2.Canny(denoised, threshold1, threshold2)
    
    # 膨胀操作让线条更连贯
    kernel = np.ones((2, 2), np.uint8)
    edges = cv2.dilate(edges, kernel, iterations=1)
    
    # 白底黑线
    result = cv2.bitwise_not(edges)
    return result


def extract_lineart(img_path, method='auto', **kwargs):
    """
    主入口:从图片提取线稿
    
    Args:
        img_path: 输入图片路径
        method: 提取方法 (canny/sketch/blend/median_edge/auto)
        **kwargs: 各方法参数
    
    Returns:
        result: 线稿图 (numpy array, 白底黑线)
        used_method: 实际使用的方法名
    """
    method_map = {
        'canny': extract_lineart_canny,
        'sketch': extract_lineart_sketch,
        'blend': extract_lineart_blend,
        'median_edge': extract_lineart_median_edge,
    }
    
    if method == 'auto':
        method, features = analyze_image(img_path)
    
    if method not in method_map:
        raise ValueError(f"未知方法: {method},可选: {list(method_map.keys())}")
    
    func = method_map[method]
    
    # 根据方法传递对应参数
    param_map = {
        'canny': ['threshold1', 'threshold2'],
        'sketch': [],
        'blend': ['blur_strength'],
        'median_edge': ['threshold1', 'threshold2'],
    }
    method_kwargs = {k: kwargs[k] for k in param_map[method] if k in kwargs}
    
    result = func(img_path, **method_kwargs)
    
    # 处理反转
    if kwargs.get('invert', False):
        result = cv2.bitwise_not(result)
    
    return result, method


def save_lineart(result, output_path):
    """保存线稿为PNG"""
    os.makedirs(os.path.dirname(output_path) if os.path.dirname(output_path) else '.', exist_ok=True)
    cv2.imwrite(output_path, result)
    return output_path


def batch_extract(input_dir, output_dir, method='auto', **kwargs):
    """
    批量处理目录下的所有图片
    
    Args:
        input_dir: 输入目录
        output_dir: 输出目录
        method: 提取方法
        **kwargs: 各方法参数
    
    Returns:
        results: 处理结果列表 [{input, output, method, status}]
    """
    os.makedirs(output_dir, exist_ok=True)
    
    supported_ext = ('*.jpg', '*.jpeg', '*.png', '*.webp', '*.bmp', '*.tiff')
    files = []
    for ext in supported_ext:
        files.extend(glob.glob(os.path.join(input_dir, ext)))
        files.extend(glob.glob(os.path.join(input_dir, ext.upper())))
    
    if not files:
        print("未找到支持的图片文件")
        return []
    
    results = []
    for f in sorted(set(files)):
        basename = os.path.splitext(os.path.basename(f))[0]
        output_path = os.path.join(output_dir, f"{basename}_lineart.png")
        try:
            result, used_method = extract_lineart(f, method=method, **kwargs)
            save_lineart(result, output_path)
            results.append({
                'input': f,
                'output': output_path,
                'method': used_method,
                'status': 'success'
            })
            print(f"  [OK] {basename} → {used_method}")
        except Exception as e:
            results.append({
                'input': f,
                'output': output_path,
                'method': method,
                'status': f'error: {str(e)}'
            })
            print(f"  [FAIL] {basename}: {e}")
    
    return results

使用示例

单张图片提取(自动模式)

from line_art_extractor import extract_lineart, save_lineart

# 自动选择最佳方法
result, method = extract_lineart("photo.jpg", method='auto')
output_path = save_lineart(result, "photo_lineart.png")
print(f"使用方法: {method},输出: {output_path}")

指定方法

# 真人照片 → 素描效果
result, _ = extract_lineart("portrait.jpg", method='sketch')
save_lineart(result, "portrait_sketch.png")

# 插画 → 灰度混合法
result, _ = extract_lineart("illustration.png", method='blend', blur_strength=25)
save_lineart(result, "illustration_lineart.png")

# 建筑效果图 → Canny
result, _ = extract_lineart("architecture.jpg", method='canny', threshold1=40, threshold2=120)
save_lineart(result, "architecture_lineart.png")

批量处理

from line_art_extractor import batch_extract

results = batch_extract(
    input_dir="./images",
    output_dir="./output_lineart",
    method='auto'
)
print(f"处理完成: {len([r for r in results if r['status']=='success'])}/{len(results)}")

反转输出(黑底白线)

result, _ = extract_lineart("photo.jpg", method='blend', invert=True)
save_lineart(result, "photo_lineart_inverted.png")

Agent 执行流程

  1. 接收输入:用户上传图片或指定图片路径/目录
  2. 自动检测:分析图片特征,推荐最佳提取方法
  3. 告知用户:说明推荐的方案及理由,询问是否使用自动推荐或手动选择
  4. 执行提取:调用对应方法生成线稿
  5. 保存输出:输出高清 PNG 到工作区
  6. 返回结果:向用户提供线稿文件链接

参数调优建议

图片类型 推荐方法 推荐参数
真人照片 sketch 默认参数
动漫插画 blend blur_strength=17(线条更细)
水彩/油画 blend blur_strength=25(保留柔和感)
建筑/产品 canny threshold1=40, threshold2=120
线条复杂的手绘 median_edge threshold1=20, threshold2=60
高对比度图像 canny threshold1=80, threshold2=200

注意事项

  1. 所有方法均在 CPU 上运行,无需 GPU,处理速度取决于图片分辨率
  2. 默认输出白底黑线(适合打印和二次上色),可用 invert=True 反转
  3. 输入图片建议分辨率不超过 4000x4000,超大图片会自动缩放处理
  4. 批量处理时会逐张分析并选择最佳方法
  5. 如果自动推荐的效果不理想,建议手动尝试其他方法或调整阈值参数
  6. 对于纯黑白漫画扫描件,直接使用 canny 方法效果最佳

依赖

库 版本要求 用途
opencv-python >= 4.0 图像处理核心
numpy >= 1.20 数值计算
Pillow >= 9.0 图像格式支持

所有依赖均已预装,无需额外安装。

相关专题

更多
Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

0

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

0

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

0

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

0

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

0

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

0

16

XORM框架结构体映射与表结构同步
XORM框架结构体映射与表结构同步

本专题围绕XORM框架的结构体映射展开,说明表名与字段的命名策略、xorm标签常用属性、主键自增与时间字段自动填充,并演示Sync2自动建表、增量字段升级、索引声明与反向生成结构体的完整流程。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

15

XORM框架安装配置与数据库连接
XORM框架安装配置与数据库连接

本专题聚焦XORM框架的配置与连接环节,拆解MySQL、PostgreSQL、SQLite、SQL Server的DSN写法与驱动选择,讲清连接池参数、多数据源拆分、读写分离与超时重连的处理方式,并补充容器与兼容数据库的适配经验。

2026.11.04

0

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习