从任意图片中提取线稿/轮廓图。支持多种方法(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" 时,根据图片特征自动推荐最佳方法:
- 图片整体对比度高 + 边缘清晰 →
canny - 图片含大量肤色/柔和渐变(照片特征) →
sketch - 色彩饱和度高/线条密集(插画特征) →
blend - 图片有噪点/纹理复杂 →
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 执行流程
- 接收输入:用户上传图片或指定图片路径/目录
- 自动检测:分析图片特征,推荐最佳提取方法
- 告知用户:说明推荐的方案及理由,询问是否使用自动推荐或手动选择
- 执行提取:调用对应方法生成线稿
- 保存输出:输出高清 PNG 到工作区
- 返回结果:向用户提供线稿文件链接
参数调优建议
| 图片类型 | 推荐方法 | 推荐参数 |
|---|---|---|
| 真人照片 | 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 |
注意事项
- 所有方法均在 CPU 上运行,无需 GPU,处理速度取决于图片分辨率
- 默认输出白底黑线(适合打印和二次上色),可用
invert=True反转 - 输入图片建议分辨率不超过 4000x4000,超大图片会自动缩放处理
- 批量处理时会逐张分析并选择最佳方法
- 如果自动推荐的效果不理想,建议手动尝试其他方法或调整阈值参数
- 对于纯黑白漫画扫描件,直接使用
canny方法效果最佳
依赖
| 库 | 版本要求 | 用途 |
|---|---|---|
| opencv-python | >= 4.0 | 图像处理核心 |
| numpy | >= 1.20 | 数值计算 |
| Pillow | >= 9.0 | 图像格式支持 |
所有依赖均已预装,无需额外安装。
热门AI工具
相关专题
本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。
0
2026.11.12
本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。
0
2026.11.12
本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。
0
2026.11.12
本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。
0
2026.11.06
围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。
0
2026.11.06
详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。
0
2026.11.06
DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。
0
2026.11.05
DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。
0
2026.11.05
本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。
0
2026.11.04
热门下载
相关下载
精品课程
共6课时 | 12.1万人学习
共79课时 | 161.8万人学习
共6课时 | 54.7万人学习
最新文章