学习Python基础语法已经有一段时间了,但是对于各种库的使用还是一知半解的,所以找了几个有意思的小项目练手,这是第一个项目:图片转换成字符画。
效果如下

大概思路如下:
根据像素值的不同在对应位置将像素值映射成合适的字符,就是像素值低的地方映射点阵占位少的字符如’.’,在像素值高的地方映射点阵占位多的字符如’$’。

首先,准备好图片转换后的字符:

charset = ['.', '!', '~', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+']

然后,根据字符再点阵中占位多少进行排序(当然,你也可以手工指定顺序),那如何知道字符在点阵字体中占点的多少呢?我们需要下载一些字库文件来解析,之后就可以知道了,这里我已经上传了一些字库文件到CSDN,可以先下载下来看一下。

需要介绍一下的是,点阵字体就是用点阵来显示字符,和TrueType有点不一样,有点类似于位图和矢量图的区别。点阵越大,字体越清晰,比如我们代码中使用的ASC16点阵文件,使用16×8(16行8列)个点来表示一个ASCII字符,一个点在文件中占1bit,读入计算机内存之后也是占1bit,ASCII码有256个,所以文件大小为16×8×256÷8 个byte= 4KB。

下面的代码读入文件并返回每个字符的点阵中为1的点有多少

def numsofone_in_charbytes(text):# 先获取字符的ascii码值offset = ord(text)# 然后打开字库文件找到该字符的位置with open("./ASC16", "rb") as ASC16:location = offset*16ASC16.seek(location)retbytes = ASC16.read(16)# 已经获取到该字符的点阵表示字节retbytes,现在要计算这16字节中有多少个1count = 0for i in range(len(retbytes)):# 对于retbytes中的每一个字节for j in range(len(KEYS)):if KEYS[j] & retbytes[i]:count += 1return count

根据上面的函数对charset中的每个字符进行排序,得到charsetnew

for s in range(len(charset)):orders[s] = numsofone_in_charbytes(charset[s])
print(orders)# 依据这个对点进行排序
# numpy.argsort()可以给出排序后各元素在原来数组中的索引
s = numpy.argsort(orders)
print(s)
# 依据上面的索引重新对charset排序
charsetnew = []
for i in range(len(charset)):charsetnew.append(charset[s[i]])

charsetnew列表中的字符就是按照每个字符点阵的填充程度从小到大排序的了,这里有一些字符的点阵中1的数目是重复的,不过没关系,影响不大。

接下来我们就要对图片进行处理了。这里图片转字符的思路是这样的,将图片看成16×8的像素块组成的,每一个像素块取平均像素值后映射成相应的字符。
首先读入图片

srcimg = matplotlib.pyplot.imread("F:/temp/testKeji.jpg")

然后对图片进行修剪,因为图片的宽高可能不是8和16的倍数,去除右方和下方多余的边。

def trim_pic(img):shape = numpy.shape(img)# 如果图片本身的长宽不满足要求就直接返回空if shape[0] < 16 or shape[1] < 8:return Noneheight = shape[0]//16width = shape[1]//8print(height)print(width)trimed_pic = img[:height*16, :width*8]return trimed_pic

图片经过修建过后,算出每个16×8(高×宽)的像素块的平均像素值,得到一个矩阵,这里其实跟卷积神经网络里面的池化操作非常像。所以我直接给这个函数取名字叫池化了

def pool16_8(img):# shape,第一个元素是矩阵行数,所以是图片的高shape = numpy.shape(img)row = shape[0] // 16cow = shape[1] // 8avgpixel = numpy.zeros((row,cow), dtype=float)for i in range(row):for j in range(cow):# 此处计算各个像素块的平均值t = 0.0for t1 in range(16):for t2 in range(8):t += img[t1+i*16, t2+j*8]avgpixel[i, j] = t/(16*8)return avgpixel

上面的函数返回一个平均像素值矩阵之后,就可以根据这个矩阵进行映射了。下面这个函数就返回一个字符矩阵

def cvt2char(avgpixel, charset):# avgpixel是计算后的像素平均值,charset是用于制作字符画的字符集chars = len(charset)race = 255.0/charsshape = numpy.shape(avgpixel)retcharmatrix = []rowchar = []for i in range(shape[0]):for j in range(shape[1]):# 获取像素的等级s = avgpixel[i, j] // race# 得到对应的字符rowchar.append(charset[int(s)])retcharmatrix.append(rowchar[:])rowchar.clear()return retcharmatrix

至此,所有的步骤都完成了。可以用一张图片测试一下,尽量选大一点的卡通图片,效果比较好,因为线条比较明显。用我最喜欢的飞天小女警来测试一下

# 读入一张图片
srcimg = matplotlib.pyplot.imread("F:/temp/PowerPuffGirls.jpg")
# 转换成灰度图
grayimg = rgb2gray(srcimg)
# 先裁剪一下
trimedimg = trim_pic(grayimg)
# 再进行池化平均
pooledimg = pool16_8(trimedimg)
# 再得到转换后的字符矩阵
charpic = cvt2char(pooledimg, charsetnew)

原图:

字符画:

有点不明显?摘掉你的眼镜试一下。
我最喜欢的花花:

效果图还不错:

当然,这里只转换成了二维的字符列表,要将这列表再转换成图片保存起来,那就是可以继续研究的地方了。
这代码里面还可以改进的地方就是可以使用边缘检测算法先对图片进行处理,然后再转换成字符画,这样对于自然图片就也会有很好的效果。
项目的完整代码我已经上传GitHub和CSDN。包括图片和完整的运行代码

Python实现的图片转字符画,附源码相关推荐

  1. 20220517 Python 制作一个儿童学习软件 (附源码和软件下载) 包含语音合成 视频播放 pyqt pptsx3 Qmovie request pygame 音频播放

    20220517 Python 制作一个儿童学习软件 (附源码和软件下载) 包含语音合成 视频播放 pyqt pptsx3 Qmovie request pygame 音频播放 文章目录 202205 ...

  2. 100个必会的python脚本-100行Python代码实现自动抢火车票(附源码)

    前言 又要过年了,今年你不妨自己写一段代码来抢回家的火车票,是不是很Cool.下面话不多说了,来一起看看详细的介绍吧. 先准备好: 12306网站用户名和密码 chrome浏览器及下载chromedr ...

  3. Python实现修改图片分辨率(含完整源码)

    Python实现修改图片分辨率(含完整源码) 在我们日常的工作和学习中,经常需要处理图片.有时候,我们可能需要修改图片的分辨率,以适应不同的需求.本文将介绍如何使用Python来实现修改图片的分辨率, ...

  4. 熬夜整理了70个Python经典实用练手项目(附源码)

    不管学习哪门语言都要做出实际的东西来,这个实际的东西就是项目. 小二整理了 70 个 Python 实战项目,都有完整且详细的教程,你可以从中选择自己想做的项目进行参考学习练手,你也可以从中寻找灵感去 ...

  5. 用Python自动刷新抢12306火车票(附源码)

    專 欄 ❈ 作者:marvin,互联网从业者,现居上海张江 ❈ 一年一度的春运又来了,今年我自己写了个抢票脚本.使用Python+Splinter自动刷新抢票,可以成功抢到.(依赖自己的网络环境太厉害 ...

  6. Python毕设-【人脸签到系统】附源码/Python练手项目/Python毕业设计

    本人承诺只做技术分享,永不收费. V----------------->:专栏详情 文章目录 本人承诺只做技术分享,永不收费. V----------------->:专栏详情 一.背景 ...

  7. Python实现将图片转字符画

    from PIL import Image # PIL 是一个 Python 图像处理库ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJU ...

  8. python (argparse库)图片转字符画小工具

    拷贝代码和图片在同一级目录下运行: from PIL import Image import argparseascii_char = list("$@B%8&WM#*oahkbdp ...

  9. python爬虫实战——自动下载百度图片(文末附源码)

    用Python制作一个下载图片神器 前言 这个想法是怎么来的? 很简单,就是不想一张一张的下载图片,嫌太慢. 在很久很久以前,我比较喜欢收集各种动漫的壁纸,作为一个漫迷,自然是能收集多少就收集多少.小 ...

  10. 一口气用Python写了13个小游戏 (附源码)

    大家好,今天给大家分享13个游戏源码,可以自己复现玩玩,研究下里面的编程逻辑,对学习编程(特别是初学者)应该会有很大帮助. 由于文章较长,大家记得滑到文末点个赞哈- 1.吃金币 源码分享: impor ...

最新文章

  1. 比特币现金足球:BCH驱动的多人世界杯应用
  2. Sqlserver 优化的方法
  3. pyCharm运行python提示“please select a valid interpreter”
  4. 哪些设计模式最值得学习
  5. C++静态库与动态库(转)
  6. 创建数组-直接法/增量法 namelengthmax isvarname iskeyword
  7. 乱七八糟的想,乱七八糟的记。
  8. JS-商品图片点击轮换
  9. spring-boot推送实时日志到前端页面显示
  10. 【c语言】小游戏程序——弹跳小球
  11. spss导入Excel显示连接服务器超时,Excel里的日期在spss里怎么不正常显示
  12. matlab中数据导入及处理,matlab 和 excel 数据的导入导出
  13. C语言判断闰年计算某月的天数代码
  14. win10开启自带wifi共享操作步骤
  15. HTML无法显示下一页,为何我的浏览器不能直接打开下一页
  16. 用VC++6.0制作简易浏览器(转)
  17. 多径效应及其消除方法
  18. springboot+Zuul网关服务
  19. r语言中的或怎么表示什么不同_R语言中$是什么意思
  20. win10软件拒绝访问删不掉_win10结束进程时拒绝访问的处理办法

热门文章

  1. 基于JAVA大学生旅游拼团网站计算机毕业设计源码+系统+数据库+lw文档+部署
  2. div嵌套的div水平垂直居中
  3. 超级玛丽java_超级玛丽java实现源码
  4. Mugeda (木疙瘩)H5案例课—交互动画类H5制作-岑远科-专题视频课程
  5. 木疙瘩动画效果视频学习
  6. Mugeda(木疙瘩)H5案例课—拍拍员工被玩坏了-岑远科-专题视频课程
  7. 普通美国人英语词汇量多少?
  8. dcdc 国产 电源芯片电路方案 选型小体积大功率高性价比推荐 不定期更新中..
  9. linphone支持 G729
  10. 线程生命周期与创建线程的多种方式