
artcraft 这个名字第一次出现在我工作目录里的时候其实只是一个随手起的文件夹名用来放那阵子画了一半的手绘稿和 AI 生成的参考图。但后来做着做着它慢慢长成了一个完整的创作小系统——把草稿扫描、AI 风格生成、统一配色、批量导出这些步骤全串在一条流水线上。这个项目解决的是困扰我很久的一个问题手工绘制和 AI 生成本来是两套完全不同的工作流手工画的时候用画板、PS、图层笔刷AI 绘图的时候又要切到提示词、采样器、模型权重。两边来回倒腾文件放得乱七八糟风格也不统一。artcraft 的思路很简单就是做一个“夹层”把两套流程粘在一起让中间过程尽量自动化我只管出图和挑图。如果你也是做插画、做独立游戏素材、做内容配图的创作者或者单纯想把手绘和 AI 生成的流程理顺那这篇文章里的经验和代码思路应该能给你不少启发。我尽量说得直接一点把设计取舍、踩过的坑和能直接落地的操作都写清楚。1. 项目定位与整体思路拆解1.1 它到底解决什么问题先说痛点。假设你今天想画一张带有手绘质感的画面常规路径是这样先在纸上起稿、扫描或者拍照进电脑用绘图软件把线稿修干净然后找参考图、做配色、铺底色、细化材质。这个过程里最难的不是画本身而是时间碎片化。一个步骤隔几天再做配色和风格早就忘了回头翻文件翻得头晕。AI 绘图工具出来以后很多人以为可以省掉中间环节直接输入提示词就有成图。实际用下来会发现AI 出图快是快但产出的图往往不是你最终想要的那张。它更像一个极其耐心的实习生给你交十版方案每一版都挺好看但都差了那么一点。真正的创作者会把 AI 结果当素材再加工而不是当成品直接用。artcraft 的项目目标就是把这两段流程接起来左手处理你的手绘草稿和素材库右手调 AI 模型做风格化最后统一输出成便于进一步精修的 PSD/PNG 图层。说白了它不是替代你做创作而是替你把繁琐的管理和风格统一工作干了。我给自己定了个原则凡是重复两次以上的操作就要在 artcraft 里变成一条命令。1.2 技术选型为什么是 Python这个项目我一开始想过用 Node.js 写后来还是老实选了 Python。原因挺现实AI 绘图相关的开源生态、模型推理库、图像处理库几乎全部都优先支持 Python追新模型和工具链会省很多事。Pillow 做基础图像操作、OpenCV 做特征处理和滤镜、ONNX Runtime 跑风格模型、FastAPI 提供 Web 控制台这些库我平时就在用组合起来没有额外学习成本。另外有一点很关键我这个项目不是给普通用户做的产品而是给创作者自己的工具链。既然是工具链就要允许我在命令行下快速调试。Python 的交互式环境配合 Jupyter Notebook可以边改参数边看效果这点对图像类实验特别友好。先在一个小脚本里跑通再封装成模块比一开始就追求工程化要高效得多。架构上我故意没有搞得太重分四块素材管理模块负责扫描和标签化目录风格服务模块负责把输入图转成目标风格资产输出模块负责统一分辨率和导出格式控制台模块负责给所有操作一个可视化入口。这四个模块之间只通过标准目录和 JSON 文件通信互不依赖任何一个坏掉都可以单独重跑。1.3 关于文件组织的三个基本原则artcraft 迭代了这么多版本文件组织上我有三个坚持了很久的原则。第一所有素材都有唯一 ID。扫描进系统的原始草稿、AI 生成过程中的中间结果、最终成稿全部按日期加序号命名比如20240105_sketch_017。文件名里带上语义信息后面做批量处理的时候就不怕搞混。第二过程文件与成品文件严格分离。working/目录下放的是中间过程output/目录下放的是最终交付两者用时间戳关联。很多人做到后面打开目录就懵了就是因为过程文件和成品混在一起根本分不清哪张是最新版本。第三配置文件全部用 YAML 而不是直接写死在代码里。每批创作的风格参数、导出分辨率、色彩配置这些都会变化写成配置项以后换一套参数只需要改一个文件不用动代码。2. 核心模块设计与实现细节2.1 素材入库与标签化素材管理是整个流水线的第一环也是最无聊但最有价值的一环。系统启动后会自动扫描指定文件夹把新增的图片比如相机拍的手绘草稿、下载的参考图、AI 生成的素材识别出来提取基础信息存到本地的 SQLite 数据库里。我实现了一个比较简单但有效的方法图片入库时先做裁剪矫正把纯色边框裁掉再用 OpenCV 检测主色调并提取色板信息同时生成一张低分辨率缩略图。缩略图这东西看起来不起眼但在批量浏览几百张素材的时候特别好用。这里分享一个实用的数据库设计图片表只存路径、尺寸、格式、拍摄时间这些标准字段单独建一个标签表存自动提取的色板文本。搜索的时候就靠标签表做 LIKE 查询虽然性能一般但胜在简单直接个人项目里完全够用。tag 提取的逻辑我写得也不复杂核心就是把颜色量化成文本。比如一张图片的主色调是暖棕色就自动打上brown/warm/dark三个标签。这样以后找素材时不需要记住文件名只输入warm palette就能把相关图片筛出来。2.2 风格迁移模块的设计风格迁移是 artcraft 的核心功能也是整个项目里迭代次数最多的部分。我试过很多路线有三思而后行的传统 CV 滤镜卡通化、油画化、有基于神经网络的风格迁移模型、也有现在的方案——通过 ONNX Runtime 调用了一个轻量级的风格化模型。选择 ONNX 而不是直接用完整 PyTorch 推理原因很简单ONNX 模型体积更小、推理速度更快、不需要装庞大的框架依赖日常在个人电脑上跑足够流畅。整个风格服务的调用逻辑大致是这样import onnxruntime as ort import numpy as np from PIL import Image def stylize(input_path, output_path, style_id): # 加载 ONNX 模型 session ort.InferenceSession(fmodels/style_{style_id}.onnx) img Image.open(input_path).convert(RGB) # 缩放到模型要求的输入尺寸一般 512x512 img img.resize((512, 512)) arr np.array(img).astype(np.float32) / 255.0 # 调整维度顺序为 NCHW arr np.transpose(arr, (2, 0, 1))[None, ...] # 模型推理 outputs session.run(None, {session.get_inputs()[0].name: arr}) out np.transpose(outputs[0][0], (1, 2, 0)) out np.clip(out * 255, 0, 255).astype(np.uint8) Image.fromarray(out).save(output_path)实际使用中你会发现模型输入尺寸直接决定生成质量。512 的尺寸速度快适合批量试风1024 尺寸细节更丰富但耗时翻倍。我在流水线里设置了两档参数初筛用快速档选中的图再跑精细档。这种做法能节省大量时间。风格模型最怕的问题是“风格过拟合”——模型把风格迁移得过于夸张细节纹理被毁掉。后来我加了一个融合参数在输出图中按比例混合原始图像的颜色信息类似传统图像处理里的混合模式效果稳定了很多。这个参数我没有固定而是放到 YAML 配置里方便按批次调整。2.3 自动配色与调色板提取做视觉创作的人应该都有这种体验一张图好不好看配色占了七成。AI 生成的图经常颜色很飘或者手绘稿在扫描后颜色偏灰偏脏。artcraft 里做了一个自动配色工具能从参考图中提取调色板然后映射到目标图上。算法本身不复杂把图片降采样到 256x256然后做颜色聚类找到前 8 个主颜色簇。我一开始用 KMeans 聚类后来发现收敛速度不稳定就换成了 OpenCV 里自带的分层树聚类速度更快且不需要指定初始中心点。得到的聚类中心就是调色板保存为 JSON后面做映射时直接读取。颜色映射过程我采用了 Lab* 色彩空间里最近邻替换的方式。RGB 空间里算距离会受到亮度影响没法正确对比颜色之间的感知差异而 Lab* 空间与人眼感知更接近。简单说就是把目标图的每个像素转换成 Lab*找调色板里最近的一个颜色替换掉重点保持亮度不变只调整色相和饱和度。这样做的好处是不同素材放一起时视觉上的调性立刻统一了。这里有个细节很影响效果映射前最好先做一次色温校正否则同一张参考图在不同光线下提取出来的色板差别会很大。我后来在入口处加了一个简单的灰度均值校正又做了一次手动的白平衡微调测试输出稳定度高了不少。2.4 批量导出流水线创作流程的最后一站是把成品导出成各种尺寸和格式。我的使用场景包括社交平台封面1200x630、独立游戏的素材切片256x256 精灵图、以及打印用的无损 PNG。不同场景需要的分辨率和色彩模式不一样手动一张张导出是很浪费时间的。artcraft 的导出器支持两种模式单图和九宫格切片。单图模式简单就是缩放、锐化、按配置保存。九宫格切片模式比较有意思它会把一张大图按指定数量均匀切成多个部分并一次性输出。我做游戏素材时非常依赖这个功能一张角色立绘直接切成动作帧省掉了在绘图软件里反复手动框选的时间。导出流程里的三个关键配置项是尺寸、格式和锐化强度。锐化强度这个参数我一开始没注意后来发现同一张图在不同尺寸下缩放后模糊程度不一样必须搭配一个合适的锐化系数。经过测试缩小到一半以上分辨率时USM 锐化半径设 1.5、强度设 80% 效果比较自然。这个经验我用表格记录在了项目的 README 里导出场景目标尺寸格式锐化强度建议社交平台封面1200x630JPEG40%素材切片256x256PNG60%打印输出原始尺寸TIFF/PNG0%尽量原样3. 实操过程把一张手绘草图变成一组插画3.1 准备阶段目录与配置文件先搭环境。项目目录有五个子文件夹input/放置手绘草稿和参考图、working/存放中间结果、output/存放最终导出、models/存放风格模型、config/存放 YAML 配置文件。你可以按自己的习惯调整但一定要在项目开始时就把分工定清楚后面就不会乱。我自己用的是 Windows WSL 环境Python 3.10需要安装的依赖如下pip install pillow opencv-python onnxruntime fastapi uvicorn安装完以后验证一下 ONNX Runtime 能否正常加载模型。先放一个简单的风格模型到models/目录运行一个最小推理测试。这个步骤排错成本最低千万别等整个系统写完了再测试。准备一张清晰的线稿放进input/目录。手绘稿要注意两点一是线条要清楚拍照时光线均匀别让阴影盖住线条二是尽量减少背景杂物纯色桌面或者纸上涂点对比色都行。这样系统在提取线稿时不会把背景噪点误判成内容。3.2 运行一次完整的流水线artcraft 的命令行入口是一个run.py接收--mode参数来区分执行哪一步。我把完整流程分成了四步每步都有对应的参数配置第一步入库python run.py --mode ingest --input input/ --working working/这一步会把input/下的所有图片扫描入库、生成缩略图、提取色板并把结果记录到数据库。跑完后打开working/目录你会看到每个图片多了一个.json的侧车文件里面存着基础信息和调色板数据。第二步线稿预处理python run.py --mode prep --file working/20240105_sketch_017.jpg这里做三件事自动裁边、灰度化、对比度增强。手绘稿扫描进去以后往往对比度不足线条不够黑背景不够白会影响后续 AI 风格化的效果。对比度增强我用的不是简单地拉曲线而是先做自适应阈值分割再把线稿和底白分离这样线条边缘能保持更自然。第三步风格化生成python run.py --mode stylize --file working/20240105_sketch_017.jpg --style config/watercolor.yamlwatercolor.yaml里配置了风格模型路径、融合参数、输出尺寸。我会在正式开始前先跑一个快速批量模式一次生成四种风格各两张小预览图。你在小图里挑出接近的意象再针对性地放大生成。这个过程有点像在海选照片效率高很多不会浪费精细生成的时间。第四步导出python run.py --mode export --file working/20240105_sketch_017_wa.jpg --config config/export.yamlexport.yaml里配置了目标尺寸和格式。跑完以后去output/目录看结果一张原始草稿变成了一组风格统一的插画基本不用再手工调。3.3 结果质检与手动修正点自动流水线跑完不代表就能直接用。我一般会打开候选图从构图、配色、细节三个维度做快速质检。构图方面AI 风格化处理可能会裁切或者丢失部分边缘信息所以需要检查主体物是否完整。配色方面要确认自动映射后的色板仍然符合原始画面的情绪设定。细节方面手绘感有没有被模型冲淡线条边缘有没有出现怪异纹理。如果发现问题我的做法不是重跑一遍那样可能生成完全不同的一张而是调整配置里的融合系数把原始结构信息的权重加大再在原图上继续处理。融合系数从 0.3 调到 0.6 往往就能解决大部分纹理失控的问题。4. 常见问题与排查技巧实录4.1 风格化结果过浓失去原图结构这是使用风格模型时遇到最多的问题。模型太强生成结果像一整幅滤镜涂上去线条和色块全糊掉了。排查时要先检查融合系数看是不是设得太低。其次看原始线稿的对比度是否足够模型在低对比度输入下容易“自由发挥”。解决办法是先对原始图做一次预处理增强再跑风格化。我在配置里增加了一个预处理开关默认开启会在风格化前做一次 CLAHE 对比度增强效果立竿见影。后续遇到类似问题时优先检查预处理步骤是否被执行而不是盲目调模型权重。4.2 ONNX 模型推理速度偶尔很慢推理速度忽快忽慢排查发现是环境里 CPU 线程调度的问题。ONNX Runtime 默认会尝试用满所有 CPU 核心但有时候和其他进程抢资源反而拖慢速度。解决办法是在初始化会话时显式指定线程数。session_options ort.SessionOptions() session_options.intra_op_num_threads 4 session ort.InferenceSession(models/style_watercolor.onnx, sess_optionssession_options)这个设置在很多个人电脑上能获得接近翻倍的推理速度提升而且能避免系统卡死。如果你用的 CPU 核心数多可以调整成cpu_count() - 2保留资源给其他操作。4.3 批量处理后内存持续上涨跑完几百张图以后Python 进程的内存占用逼近 2GB明显是内存泄漏。排查后发现两个问题一是 OpenCV 处理完每张图后没有释放 Mat 对象二是 Python 列表里存了所有图片的调色板信息一直没有清理。解决办法是在循环尾端显式调用cv2.destroyAllWindows()和gc.collect()并把调色板数据写成 JSON 文件后再从内存移除。做了这个优化以后内存占用稳定在了 300MB 左右再跑几百张也不会爆。4.4 导出的 PNG 在部分软件里显示背景发灰有一次导出 PNG 后在游戏引擎里显示发灰排查发现是颜色模式的问题。Pillow 保存 PNG 时默认带 Alpha 通道我在导出时没有显式转换导致部分引擎把它当成了带透明度的颜色空间。修正方法也简单保存前先判断是否需要展平 Alpha 通道。这里贴一下我当时用的函数def save_png(image, path, flatten_alphaFalse): if flatten_alpha and image.mode RGBA: background Image.new(RGB, image.size, (255, 255, 255)) background.paste(image, maskimage.split()[-1]) image background image.save(path, formatPNG)这个细节在打印和游戏制作场景里特别重要提前处理可以省掉一趟返工。4.5 小图放大后边缘锯齿严重自动导出时如果原图分辨率较低直接缩放到目标尺寸会出明显锯齿。我开始以为锐化能解决其实不行。后来加了两步第一步先用高质量插值算法做平滑放大第二步再做轻度锐化。平滑放大我用的是 LANCZOS 插值比默认的 BICUBIC 干净很多边缘过渡自然锐化后再看基本不影响观感。5. 实用心得与后续扩展方向5.1 几条经验总结artcraft 这个项目做下来我的核心体会是创作工具链的价值很多时候不在于用多高级的算法而在于把例行公事的部分自动化把省下来的时间留给真正需要判断力的环节。第一配置驱动比代码驱动更适合这类项目。你在创作时变动的往往不是逻辑而是参数。把这部分抽出来放 YAML改动就不用翻代码更安全也更直观。第二每个环节都要保留中间产物。风格化之前的线稿、调色板映射之前的原图这些中间结果在出问题时就是最好的排查线索。第三尽量早地做可视化。没有控制台的时候我只能靠命令行参数和输出目录猜问题加了一个简单的 FastAPI 页面批量选择候选图的效率至少提升了一倍。这个控制台不需要做得很复杂我用 FastAPI 起了个本地服务渲染一个包含缩略图网格的 HTML 页面点击图片就能标记“候选”或“弃用”所有标记存到 JSON 里。比命令行逐张挑选直观太多了。如果你也想加这个功能代码量大约四五十行很值得。5.2 可以继续扩展的方向artcraft 目前覆盖的还只是静态图片的流水线。我自己打算下一步扩展两个方向一个是动画素材支持把逐帧 PNG 序列纳入流水线让风格模型处理连续帧时保持帧间一致性另一个是矢量导出兼容尝试把风格化后的位图结果转成 SVG 线稿方便做更灵活的后期编辑。如果你是在做独立游戏我还建议在这个基础上加一个“素材表”系统把导出后的图自动生成一份清单标好名称、尺寸、用途直接给程序同事用能省掉不少沟通成本。写在最后artcraft 这个项目到现在还在持续迭代但核心的价值已经验证了一条能把草稿、AI 生成、配色、导出串起来的自动化流水线确实能大幅解放重复劳动。如果你也有类似的素材处理困扰我建议从最小可用的版本开始先把最烦人的一个环节自动化了再慢慢加功能。工具是拿来用的没必要一上来就追求完美。最后分享一个我踩过几次坑的小技巧任何一步自动操作完成之后都先手动随机检查三五张图再批量跑。自动化流程建立之后最怕的不是跑不动而是跑得很顺但是结果全错了你到最后才发现。花一分钟抽查比事后返工几小时划算得多。