如何用python制作字符图_Python制作字符图片

背景

字符图片,即纯使用字符构造出一幅图片。关于这个,网上的教程和程序已经非常多了,都是使用不同复杂程度的字符模拟图片的灰度(比如字符'@'就比字符','复杂,但是我要做的是像这样的:(原图是星之卡比)

------------------

---(() ----------------/((/---

-()/--- ---(()--

--(//- --\/--

-/()-- -)//--

/(/(- --/)-- -\//\ )\/\

/()- )\( \\ /)- -(( -\/\

/ / (| ) | |(| |) ) \

-/ ( | \--- | | \--/-|| \\\-

--/(|)( | | | || -(|()--

//\-( -( |(|---\ | |((---|| )//-\/)\

/()(- -- ---- ----- -/( //) \)- /-( ---------- - --(/\

/ / || - - | )())/- -\(\)/ | || || )/\

/ ( |\ ---------- -(\- --(- ---------- )| )(\

|(| |/( ---// -- )\| \ |

|((- |)( /(| -) |

\/\\------ -/\ -(-/-------) /

\()\--- (\/\( /()\| --/-(//

---/\ \ -\ // ) /)/( ---

\()- \- -/--// /

---\/\------ -/-- -/ \--

/-)/- -\/\ ----- ------ -/ /----/--

/(/- --()-- ------- ------ --/\-- -\/\-

-/ / --(/\-- ------------------ --/-(\--- -\/\

)(/ -- ---//)--\- -----\)/-- --) \

|) - / --- /()()/------( \( ---- |( \\)(

|| -- /\/----\/\ -\- --| |

\/( ---(/-- --(/-- --- ///|

\()--- --- ()/-- --- ()/\--- ---- \//

----/(((/\ ---- ---- (/(\/( )/()() ---

即使用斜杠、减号等符号围出图案的边缘构造图片,和Linux下的figlet、toilet等程序效果类似,但是这两个程序只能构造艺术字,这个程序能够处理任意图片,因此在此分享一下。

思路

首先,要用符号围出图案的边缘,需要能够知道图案的边缘在哪。这个可以用OpenCV库里的Canny边缘检测函数检测出来。之后就是研究如何用字符围出来,我采用了像素比较的方法,将图片分成一定数量相同大小的子图片,对于每个子图片,我将其和用到的所有字符的图片计算一个“欧几里得距离”(即所有像素差值的平方和),选取一个差值最小的字符作为这个像素对应的字符。

程序中还有两点细节,一是我做边缘检测前后各做了一次放缩,第一次是为了方便边缘检测,第二次是适应不同的字符拟合需求,有的时候需要尽量少的字符,则需要在拟合前把图片缩小,有时希望拟合的效果更好,这时需要在拟合前把图片放大;二是为了防止子图片中边缘的像素点偏离图片中心,导致拟合出现错误,所以我在比较前把字符图片和边缘像素点都对齐到图片中心。

代码

import cv2

import numpy as np

from matplotlib import pyplot

from PIL import Image, ImageDraw, ImageFont

first_scale = 1 # 第一次放缩倍数

detection_strength = 80 # 边缘检测强度

second_scale = 1 # 第二次放缩倍数

block_width = 10 # 子图片宽

block_height = 25 # 子图片长,可以通过调整这两个参数适应不同显示环境字符的高矮胖瘦

img = cv2.imread('Kirby.jpg')

img = cv2.resize(img, (0, 0), fx=first_scale, fy=first_scale) # 第一次放缩

img = cv2.Canny(img, detection_strength, detection_strength * 3) # 边缘检测

kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))

img = cv2.dilate(img, kernel) # 膨胀边缘检测后的图片,让边缘清晰完整

img = cv2.resize(img, (0, 0), fx=second_scale, fy=second_scale) # 第二次放缩

chars = ['/', '\\', '(', ')', '|', '-', ' '] # 用到的字符

chart = {}

font = ImageFont.truetype('C:\\Windows\\Fonts\\simhei.ttf', 20) # 这里指定字符图片的字体为黑体,可换成别的

for i in chars:

if i != ' ':

chart[i] = np.zeros((20, 10), np.uint8)

t = Image.fromarray(chart[i])

draw = ImageDraw.Draw(t)

draw.text((0, 0), i, font=font, fill=255) # 这里用PIL制作字符图片,其绘制字符的函数比OpenCV好控制

chart[i] = np.array(t)

chart[i] = cv2.resize(chart[i], (block_width, block_height)) # 把字符图片缩放为子图片的大小

t = np.where(chart[i] > 0)

y1, y2 = np.min(t[0]), np.max(t[0])

x1, x2 = np.min(t[1]), np.max(t[1])

w = x2 - x1 + 1

ws = (block_width - w) // 2

h = y2 - y1 + 1

hs = (block_height - h) // 2

t = np.zeros((block_height, block_width), np.int32)

t[hs:hs + h, ws:ws + w] = chart[i][y1:y2 + 1, x1:x2 + 1] # 把字符实际像素对齐到图片中心

chart[i] = t

else:

chart[i] = np.zeros((block_height, block_width), np.int32)

s = ''

for i in range(0, img.shape[0] - block_height, block_height):

# 如果显示图片的地方默认有行距,比如单倍行距,则可以把上面这句话改成for i in range(0, img.shape[0] - block_height, block_height * 2):

for j in range(0, img.shape[1] - block_width, block_width): # 枚举子图片

mn = 0x3fffffff

mx = ' '

block = img[i:i + block_height, j:j + block_width]

t = np.where(block > 0)

if t[0].shape[0] != 0 or t[1].shape[0] != 0:

y1, y2 = np.min(t[0]), np.max(t[0])

x1, x2 = np.min(t[1]), np.max(t[1])

w = x2 - x1 + 1

ws = (block_width - w) // 2

h = y2 - y1 + 1

hs = (block_height - h) // 2

t = np.zeros((block_height, block_width), np.int32)

t[hs:hs + h, ws:ws + w] = block[y1:y2 + 1, x1:x2 + 1] # 将子图片边缘像素对齐到图片中心

for k in chars:

a = np.sum((t - chart[k]) ** 2) # 计算欧几里得距离(省略开方)

if a < mn:

mn = a

mx = k

s += mx

s += '\n'

print(s)

pyplot.imshow(img, cmap='gray')

pyplot.show()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图片转化为字符画。需要先安装PIL。推荐下载PIL包来实现。 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - - - - - - - - - - - - - - * * * * * * * * * * * * * * * * + + + + + + + + + + + + + + + + + + + + * - - - - - - - - - - - - - - - * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * * - - - - - - - - - - - - - - - * * * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / / / / / / / / / / / / / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / / / / / / / / / / / / / / / / / / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # / / / / / / / / / / / / / # # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # / / / / / / / / / / / / / # # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # / / / / / / / / / / / / / # # + + + + + + + + + + + + + + + + + + + + + + + + + + + # # # # # # # # # # # # + / / - - - - - - - / # # # # # # # + + + + + + + + + + + + + + + + + + + + + + # # # # # # # # # # # # + / / - - - - - - - / # # # # # # # + + + + + + + + + + + + + + + + + + + # # # # # # # # # # # # # # # + / / / / / - - / / / # # # # # # # # # # + + + + + + + + + + + + + + + + # # # # # # # # # # # # # # # + / / / / / - - / / / # # # # # # # # # # + + + + + + + + + + + + + + + + # # # # # # # # # # # # # # # + / / / / / - - / / / # # # # # # # # # # + + + + + + + + + + + + + + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * + + + + + + + + + / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * + + + + + / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / + # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / / # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / / / / / / / / # # # # # # # # # # # # # # # # # + / / / / / / / / / / # # # # # # # # # # # # * / / / / /

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值