用PIL,一个强大的python图像处理库。主要用到了Image。
终端下载命令:
pip install pillow
自己在东方明珠上拍到的黄浦江是多么美丽!但想到这里就回忆起儿时画风景画苦不堪言的感觉,心想一定要写个程序帮自己完成美术作业。
最简单的一步,就是把彩色图片转为黑白图片。
from PIL import Image #导入PIL库
d = input("Img Directory:") #输入要处理的图片路径
img = Image.open(d).convert('LA') #直接处理
img.save('greyscale.png') #保存图片
怎么样?是不是很简单?
用了自己在东方明珠上拍到的黄浦江,下面是效果图:
会了简单的转黑白,试试更难的转ascii字符画。代码如下:
from PIL import Image #导入PIL
#生成ascii图的宽度和高度。建议和原图比例类似。
WIDTH = 300
HEIGHT = 200
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") #字符DPI(Dots Per Inch,每英寸点数)从高到低排序
#把彩色图转化为灰度图,然后将256个灰度映射到70个字符上
def get_char(r, g, b, alpha=256): #R红G绿B蓝A透明度
if alpha == 0: #空白像素返回空格
return ' '
length = len(ascii_char) #
gray = int(r*0.299 + g*0.587 + b*0.114) #计算灰度,3:6:1是比较靠谱的
unit = (256.0+1)/length
return ascii_char[int(gray/unit)]#不同的灰度对应着不同的字符
d = input("Img Directory:") #输入图片路径
img = Image.open(d) #打开文件
img = img.resize((WIDTH, HEIGHT), Image.NEAREST) #变得小一点好处理
txt = "" #临时储存字符画信息
for i in range(HEIGHT): #遍历每一个像素点
for j in range(WIDTH):
txt += get_char(*img.getpixel((j, i))) #获得DPI最接近的字符
txt += '\n' #写完一行就换行
with open("ascii_picture.txt",'w') as f: #写到txt文件里储存
f.write(txt)
注意字体要用mono space,比如python IDLE默认的monaco字体,不要其它格式哦!不然会乱七八糟的
博主很懒没有写代码自动修改宽高,小伙伴们可以自己动动脑子修改一下
计算灰度我也偷懒了,直接代数求值,但有很多其它更好用更准确的算法
感兴趣的同学可以看看Gamma校正算法,转化成物理光功率会更准确哦!
效果图如下:
这是我截图的,因为太密集所以出现了莫尔条纹。300x200还是有点离谱,可以用小一点的。但是还原还是很到位的!
到了这一点,python图像处理功能看起来更强大了。代码如下:
from PIL import Image #导入PIL
d = input("Img Directory:") #输入图片路径
img = Image.open(d) #打开图片
img_all = "素描" + d #存储生成文件的位置
new = Image.new("L", img.size, 255) #创造新文件,大小和原来文件一样
width, height = img.size #不偷懒了,获得图片大小
img = img.convert("L") #变成灰度,其实PIL用的也是简单算法
Pen_size = int(input('Pensize:')) #画笔大小
Color_diff = int(input('Color diffusion variable:')) #色差扩散器
#简单说大概就是ps里的颜色减淡模式啦……
#作用就是把色差较大的色块交界线保留下来
for i in range(Pen_size + 1, width - Pen_size - 1):
for j in range(Pen_size + 1, height - Pen_size - 1):
originalColor = 255
lcolor = sum([img.getpixel((i - r, j)) for r in range(Pen_size)]) // Pen_size
rcolor = sum([img.getpixel((i + r, j)) for r in range(Pen_size)]) // Pen_size
if abs(lcolor - rcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
ucolor = sum([img.getpixel((i, j - r)) for r in range(Pen_size)]) // Pen_size
dcolor = sum([img.getpixel((i, j + r)) for r in range(Pen_size)]) // Pen_size
if abs(ucolor - dcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
acolor = sum([img.getpixel((i - r, j - r)) for r in range(Pen_size)]) // Pen_size
bcolor = sum([img.getpixel((i + r, j + r)) for r in range(Pen_size)]) // Pen_size
if abs(acolor - bcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
qcolor = sum([img.getpixel((i + r, j - r)) for r in range(Pen_size)]) // Pen_size
wcolor = sum([img.getpixel((i - r, j + r)) for r in range(Pen_size)]) // Pen_size
if abs(qcolor - wcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
new.save(img_all) #保存图片
我的MacBook Air i5 1.6GHz芯片鬼哭狼嚎了不知道多久,还是没办法把原图处理出来……
测试了下,处理一个256x256的图也就几秒钟时间。小伙伴们可以先把图片分辨率调低再处理
我选择的画笔大小是5,色差扩散器也是5,效果看起来还不错。
好了,现在可以和其它小伙伴炫耀你的画技了!
RGB转灰度的算法有很多分类,可以搜一下有关算法,看看能不能做到准确地把灰度图片还原成彩色图片。本人试了试pillow的算法把灰度转为彩色,发现还原出来的图片人类还是不太能接受的
选用画笔大小和色彩扩散器的时候可以自己尝试下不同值出来的效果噢!
可以在画素描的时候加一个自动调整图片大小的代码,这个问题交给各位来解决喽
其实画素描的算法可以有很大提高,比如加一个随机函数让笔画更加自然,或者干脆换一种算法让它变得更快。相关资源网上有很多,就不再赘述了