字符线描转换器 v1.0 ——用 ─ ╱ │ ╲ 把照片描成线稿
本文最后更新于26 天前,其中的信息可能已经过时,如有错误请发送邮件到 sunrisetsn@gmail.com

〇 前言

这是第二台图片转换器,前面分别是 ASCII 字符画、AI虚拟白板。这一台的玩法是“字符线描”——放一张图进去,它先用方向字符 ─ ╱ │ ╲ 把轮廓描成一张字符线描,再重新渲染回一张干净的黑白线稿。

跟第一台 ASCII 字符画最大的区别,是思路反过来了:ASCII 画用 @#*· 这些字符的疏密去表现明暗,这一台是拿字符本身当画笔,笔画的朝向去贴合轮廓的朝向。

期间踩了一堆坑,最离谱的是迟滞连接那步的死循环,少写了一个 `& ~edges` 直接卡到天荒地老,后面会讲。

一 功能

  • 图片 → 字符线描文本(方向字形勾勒轮廓),存 `.txt`
  • 字符线描文本 → 图片:等宽字体按栅格逐字渲染,输出 `.png`
  • 字形集二选一:盒绘制 `─╱│╲` 或 ASCII `-|\`
  • 深色背景 / 点状背景 / 淡描(弱边缘用 `·` 勾,铅笔素描感)
  • 彩色线描(按原图颜色上色)
  • 阴影效果(偏移 + 高斯模糊的柔和投影)
  • “保存到…”自选输出路径
  • 命令行 + GUI 双入口,PyInstaller 单文件 exe

二 技术栈

技术用途
Python 3开发语言
NumPySobel 梯度、非极大值抑制、迟滞连接、方向统计
Pillow图像读写、灰度缩放、等宽字体渲染、投影模糊
PySide6(Qt)GUI 界面、图片与字符画预览、文件对话框
PyInstaller打包为单文件 exe

三 使用到的主要模块

①NumPy(核心)

整条边缘检测流水线都是它手写的:

函数作用
`_conv1d_rows/_conv1d_cols`可分离卷积,Sobel 和去噪都靠它
`_nms()`非极大值抑制,把粗边压成单像素细线
`_hysteresis()`双阈值 + 迟滞,只留连贯清晰的边
`arctan2(Σ sin2φ, Σ cos2φ)`方向圆平均,0°/180° 不打架

②Pillow

`Image.open` 原生支持中文路径,省了 OpenCV 那套 `imdecode` 的麻烦;`ImageFont.truetype` 用等宽字体把字符逐个画回栅格,阴影的高斯模糊也是它的 `ImageFilter.GaussianBlur`。

③PySide6

`QLabel` 显示原图和结果图、`QTextEdit` 显示字符画文本、`QFileDialog` 选图和自选保存路径、`QCheckBox/QComboBox` 那一排参数控件,跟前面三台共用同一套 GUI 骨架。

四 实现原理

图片 │ 灰度 + gamma

高斯去噪 → Sobel 梯度(幅值 + 方向)

非极大值抑制 → 双阈值迟滞(边缘掩码)

按字符块取边缘方向圆平均 → 量化 0°/45°/90°/135°

映射方向字形 ─ ╱ │ ╲ → 字符线描文本(.txt)

等宽字体逐字栅格渲染 → 线稿图片(.png)

方向是这么算的:Sobel 求出梯度法线,法线转 90° 就是线条方向 φ;每块内的边缘方向用倍角法做圆平均,再量化到四个方向,映射成 ─ ╱ │ ╲(或 ASCII 的 – / | \)。

五 字符线描效果

线描的“笔触”不是靠明暗,而是靠方向——于是轮廓的横竖斜被不同字符“描”出来,放大是一排排字符,缩远就是干净的线稿。阴影则是把墨迹的 alpha 偏移 + 高斯模糊后叠回画布,线稿一下子“浮”起来了:

代码说明
`φ = (atan2(gy, gx) + 90°) % 180°`梯度法线转线方向
`mean = atan2(Σ sin2φ, Σ cos2φ) / 2`倍角法圆平均
`sh.paste(alpha, (dx, dy)) + GaussianBlur`阴影偏移 + 模糊
`canvas.alpha_composite(shadow)`投影叠回画布

六 踩过的坑(重点)

  • 迟滞连接死循环:强边缘播种、弱边缘连通那步,少写了 `& ~edges` 这个条件,循环会一直重复吸收同一批像素,直接卡死。加上之后才收敛,这是全场最阴的一个。
  • ImageFilter 漏导入:阴影模糊用到 `PIL.ImageFilter.GaussianBlur`,一开始 import 漏了,跑到渲染那步直接 NameError。补一行 import 就好。
  • 打包时 exe 被占用:前面冒烟测试起的进程没杀干净,PyInstaller 最后一步覆盖旧 exe 时抛 PermissionError。把 `LineArtConverter.exe` 进程 force 杀掉再打一次就过了。
  • 方向字形显示乱码:box 字形在 Windows 控制台里是 GBK,打印出来全变成 �;其实文件里是好的 UTF-8,换成等宽字体渲染就正常了。

七 开发记录

四台转换器做下来,越来越觉得“字符 + 图像”这个方向有意思——同样的输入,换一种映射规则就是完全不同的观感。这台最大的收获,是把 Canny 那套边缘检测亲手用 numpy 重写了一遍,对“边缘方向”的理解比看十遍教程都深。

目前是 v1.0 够用了,之后想加:导出矢量 SVG、笔触平滑、书法笔画字形集、一键批量处理,把它一步步做得更接近“能直接当海报线稿用”的样子。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇