Python帮你完成美术作业——图片转灰度,字符画,素描手绘风格

Python图像处理——图片转黑白,字符画,手绘风

实现原理

用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

会了简单的转黑白,试试更难的转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校正算法,转化成物理光功率会更准确哦!
效果图如下:
ascii画
这是我截图的,因为太密集所以出现了莫尔条纹。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的算法把灰度转为彩色,发现还原出来的图片人类还是不太能接受的

选用画笔大小和色彩扩散器的时候可以自己尝试下不同值出来的效果噢!

可以在画素描的时候加一个自动调整图片大小的代码,这个问题交给各位来解决喽

其实画素描的算法可以有很大提高,比如加一个随机函数让笔画更加自然,或者干脆换一种算法让它变得更快。相关资源网上有很多,就不再赘述了

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EricFrenzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值