4. 不借助AI也可以实现图片转线稿
约 849 字大约 3 分钟
最近准备实现一个根据图片生成简笔画的应用,研究了下现在的ai能力,在使用百度的图片提取线稿的时候发现AI处理能力是真的强,比如下面是几个提取case

从整体的实现效果来看,还是非常不错的,对于现实人物、3d图、2d卡通、建筑的线稿提取结果可以说几近完美了。唯一的小问题就是处理时间长了一点,也不免费...
那么有没有其他开源的工具可以直接使用呢,发现了两个有意思的开源项目,一个是基于机器学习训练结果的,另一个则是直接使用算法(代码行<50行)进行提取转换
基于训练模型 rocca/informative-drawings-line-art-onnx
模型地址-> https://huggingface.co/rocca/informative-drawings-line-art-onnx
项目源码:https://github.com/josephrocca/image-to-line-art-js
使用约17兆的模型即可实现线图提取功能,下面是官方的demo表现情况

从上面的处理结果也可以看出,对于卡通图像的转换效果还是可以的;但是对于显示人物、建筑之类的效果就一一般般了
算法提取
项目源码:Outline-Extractor
核心算法
function calculate() {
loadingMsg.className = 'hide';
const ch = canvas.height = this.naturalHeight;
const cw = canvas.width = this.naturalWidth;
ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0);
const imdata = ctx.getImageData(0, 0, cw, ch);
const c = imdata.data;
const imgray = [];
for (let i = 0; i < c.length; i += 4) {
const Y = (0.3 * c[i] + 0.59 * c[i + 1] + 0.11 * c[i + 2]);
imgray.push(Y);
}
const mina = []
for (let h = 0; h < ch; h++) {
for (let w = 0; w < cw; w++) {
const u = max(0, h - 1);
const d = min(ch - 1, h + 1);
const l = max(0, w - 1);
const r = min(cw - 1, w + 1);
mina.push(255 - max(
imgray[u * cw + l], imgray[u * cw + w], imgray[u * cw + r],
imgray[h * cw + l], imgray[h * cw + w], imgray[h * cw + r],
imgray[d * cw + l], imgray[d * cw + w], imgray[d * cw + r]));
}
}
const result = [];
for (let i = 0; i < imgray.length; i++) {
const Y = imgray[i];
const M = mina[i]
result.push(Y + (Y * M) / (255 - M));
}
for (let i = 0; i < c.length; i += 4) {
c[i] = c[i + 1] = c[i + 2] = result[i / 4];
}
ctx.putImageData(imdata, 0, 0);
pImg.src = canvas.toDataURL();
}
在线体验地址: https://ai.hhui.top/app/imgline.html
整体表现效果如下:

从实际的效果来看,和上面的训练模型的处理结果半斤八两,不过好处也很明显,处理效率明显更高,且无外部依赖
小结
下面是具体的对照结果,对于卡通图片,如果希望提取线稿,会发现即便不使用大模型、机器学习的能力,借助最基础的算法处理,不超过50行的代码也可以实现相对理想的效果
原图 | 百度提取线图 | 训练模型处理 | 算法提取 |
---|---|---|---|
![]() | ![]() | ![]() | ![]() |
![]() | ![]() | ![]() | ![]() |
![]() | ![]() | ![]() | ![]() |
![]() | ![]() | ![]() | ![]() |
Loading...