图像转字符画

这是我第一个正经的python程序,之前的无非是照抄廖大佬的教程胡乱试探的小程序。在敲这个程序之前,用了一个周末熟悉python的语法,廖雪峰老师的教程真的很棒!
在敲这个程序之前,我遇到许多烦心的小问题,在这里写下来也许对您有些帮助

0.设置模块路径

因为我用的是mac,自带了python,在敲这个程序之前用的都是python2.x,然而,当我想用python3.7编写程序时,却出了问题
首先是PIL库,我当时一句pip install pillow以为就能解决问题,在编译的时候pycharm却总是告诉我找不到pillow模块(我当时写的是from pillow import Image, ImageFont, ImageDraw )
后来发现,应该是

from PIL import Image, ImageFont, ImageDraw

然而,还是不行,它继续报错,PIL模块也找不到,接下来我就开始了漫长的浏览各种博客,发现我犯的错误真是不止一个
首先,pillow用不了是因为我是后装的python3.7,通过pip下载的pillow不在它默认的模块文件夹里
于是我先是这样:

>>>import sys
>>>sys.path

然后它告诉我

['', '/anaconda3/lib/python37.zip', '/anaconda3/lib/python3.7', '/anaconda3/lib/python3.7/lib-dynload', '/anaconda3/lib/python3.7/site-packages', '/anaconda3/lib/python3.7/site-packages/aeosa']

退出python3,我又

$ pip install pillow

(因为这样可以让pip告诉你pillow装在哪里了)
然后它说

Requirement already satisfied: pillow in /usr/local/lib/python2.7/site-packages (5.3.0)

进去一看,还真有(在这之前我还查了一下为什么我的mac看不到usr文件夹,我是有多菜……,其实查之前我还查了一下mac咋进入根目录……)
在这里插入图片描述
点进去一看,PIL很大的样子,pillow只有几个文件,我猜是用来给python3.x适配的,看来这个PIL必须要和pillow在一起python3.x才能用
现在pillow和PIL不在python3默认的模块路径里,我就把它复制过去呗
然后它又报错了

ImportError: dlopen(/Users/blind/Desktop/python/newbie/PIL/_imaging.so, 2): Symbol not found: _PyInt_AsLong
  Referenced from: /Users/blind/Desktop/python/newbie/PIL/_imaging.so
  Expected in: flat namespace

干啊,这又是为啥啊!

在这里插入图片描述
在stackoverflow上查了一下这个错误,突然明白我为什么是智障了……
下载pillow时的命令应该是

pip3 install pillow

应该用pip3,而不是pip!!!
我再pip3一遍,发现针对python3的模块文件夹就在python2的右边

把里面的PIL和pillow复制到项目的文件夹下,我再

from PIL import Image, ImageFont, ImageDraw

好感动,终于正常运行了

1.查查pillow模块咋用

发现我们要用到Image, ImageFont, ImageDraw这三个模块以及里面的各种函数
先把用到的函数贴出来,具体咋用后面再讲

  • Image模块
函数名 解释
Image.open(“x.x”) 打开一个图像文件
im.size 它的返回值为宽度和高度的二元组(width, height)
Image.new(mode, size, color) 新建一个图像文件
im.resize 缩放
  • ImageFont模块
函数名 解释
ImageFont.load_default() 加载一个默认的字体
  • ImageDraw模块
函数名 解释
Draw(image) 创建一个可以在给定图像上绘图的对象
draw.text(position,string, options) 在给定的位置绘制一个字符

2.开始敲

第一次独立敲python还有点小紧张,之前简单的看了一眼做字符画的教程,因为想满足自己的某种成就感,决定具体的代码还要自己敲!
发现pillow离不开Image类,用Image类的open函数

from PIL import Image
im = Image.open('666.jpg','r')

就能打开项目文件夹下的hhh.jpg文件了
同时我们要获取这个图像的长和宽,用im.size就ok

w,h=im.size

然后顺手再新建一个大小一样的图像,用来储存我们之后画出来的字符画

newIm= Image.new("RGB",im.size, (150, 150, 150))

其中(150,150,150)表示新建图像的背景颜色,因为我有强迫症就选了整数

然后就要我们识别图片里的每一个像素,这里要用到getpixel函数,只要这样

im.getpixel((x, y))

就可以得到某个像素点的颜色,一般返回(r, g, b),然后我们建一个列表color先把每个像素点的RGB参数存下来
再新建一个字符串,每对应一个像素存一个字符,这里我就比较骚了,可以这样玩

char = "ILOVEYOU"

def GetChar(number):
    return char[number%8]

然后只要在循环里每次对number加1,就可以连续输出ILOVEYOU了
把每个像素都对应一个字符输出到字符串里,我们就得到了一个文本文件(别忘了敲回车,不然所有像素对应的字符就都在一列了)
然后我们用ImageDraw类的Draw函数,像这样

draw =ImageDraw.Draw(newIm)

就创建了一个可以在上面绘图的对象,以后对图片的处理都在draw这个对象上进行,但newIm也会跟着改变
接下来要获取系统默认的字符信息,分别是字符的宽和高

fontW,fontH=ImageFont.load_default().getsize(char[0])

接下来我们只要把txt中对应的字符串和和colors中每个像素的颜色结合绘制在draw上就完工了
然后运行,干啊,为什么只有原图的一小部分?!
原来是一个像素对应一个字符导致图像太大了
那我们只需要做一些小小的改动

newW = int(w/fontW)
newH = int(h/fontH)
im = im.resize((newW,newH), Image.NEAREST)

把im根据系统默认的字符大小缩放,然后在新的im中获取像素的颜色信息
这次终于成功了!!!
附上代码和图片

# -*- coding:utf-8 -*-
from PIL import Image, ImageFont, ImageDraw

char = "ILOVEYOU"

def GetChar(number):
    return char[number%8]

im = Image.open('666.jpg', 'r')
w,h=im.size
newIm = Image.new("RGB", (w,h), (150, 150, 150))

fontW, fontH = ImageFont.load_default().getsize(char[0])

newW = int(w/fontW)
newH = int(h/fontH)
im = im.resize((newW,newH), Image.NEAREST)
txt = ""
colors = []
number = 0
for i in range(newH):
    for j in range(newW):
        pixel = im.getpixel((j, i))
        colors.append((pixel[0], pixel[1], pixel[2]))

        txt += GetChar(number)
        number += 1

    txt += '\n'
    colors.append((0, 0, 0))

draw = ImageDraw.Draw(newIm)


x = y = 0
for i in range(len(txt)):
    if (txt[i] == '\n'):
        x += fontH
        y = -fontW

    draw.text([y, x], txt[i], colors[i])
    y += fontW
newIm.save('999.jpg')
newIm.show()

666999

猜你喜欢

转载自blog.csdn.net/weixin_43263346/article/details/85132295