python + opencv 入门项目 【python图片转字符画】

基础知识

  • 命令行获取python当前工作路径

import os
os.getcwd()
  • 安装pillow库

pillow库
PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。
由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此,我们可以直接安装使用Pillow。
廖雪峰的官方网站

pip install pillow
  • 简单操作图像

1. Image 模块

缩放图片

 from PIL import Image
 
# 打开一个jpg图像文件,注意是当前路径:
im = Image.open('test.jpg')
# 获得图像尺寸:
w, h = im.size
print('Original image size: %sx%s' % (w, h))
# 缩放到50%:
im.thumbnail((w//2, h//2))
print('Resize image to: %sx%s' % (w//2, h//2))
# 把缩放后的图像用jpeg格式保存:
im.save('thumbnail.jpg', 'jpeg')

生成缩略图
thumbnail函数接受一个元组作为参数,分别对应着缩略图的宽高,在缩略时,函数会保持图片的宽高比例。如果输入的参数宽高和原图像宽高比不同,则会依据最小对应边进行原比例缩放。
thumbnail参数意义

image模块函数 用法
open 打开一个图像
size 获得图像尺寸
thumbnail 生成缩略图
save 保存图像

2. ImageFilter 模块

模糊图

from PIL import Image, ImageFilter

# 打开一个jpg图像文件,注意是当前路径:
im = Image.open('test.jpg')
# 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')

3. ImageDraw 模块

生成字母验证码图片

from PIL import Image, ImageDraw, ImageFont, ImageFilter

import random

# 随机字母:
def rndChar():
    return chr(random.randint(65, 90))

# 随机颜色1:
def rndColor():
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

# 随机颜色2:
def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

# 240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36)
# 创建Draw对象:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x in range(width):
    for y in range(height):
        draw.point((x, y), fill=rndColor())
# 输出文字:
for t in range(4):
    draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
# 模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')
Image模块函数 用法
Image.new Image.new( mode, size, color ) => image

ImageFont模块定义了相同名称的类,即ImageFont类。
这个类的实例存储bitmap字体,用于ImageDraw类的text()方法。

ImageFont模块函数 用法
ImageFont.truetype TrueType采用几何学中二次B样条曲线及直线来描述字体的外形轮廓,其特点是:TrueType既可以作打印字体,又可以用作屏幕显示;由于它是由指令对字形进行描述,因此它与分辨率无关,输出时总是按照打印机的分辨率输出。无论放大或缩小,字符总是光滑的,不会有锯齿出现。但相对PostScript字体来说,其质量要差一些。特别是在文字太小时,就表现得不是很清楚。

运行时报错:OSError: cannot open resource
这是因为PIL无法定位到字体文件的位置,可以根据操作系统提供绝对路径,比如:

'/Library/Fonts/Arial.ttf'

或者是因为找不到该字体

stackoverflow:
It is obviously font file cannot be found by PIL.
In font = ImageFont.truetype(“arial.ttf”, 15), arial.ttf cannot found.
The solution is cd /usr/share/fonts/truetype and find a available font file then replace “arial.ttf” with it.(For windows user, font files in C:\WINDOWS\Fonts)

imageDraw模块函数 用法
draw = ImageDraw.Draw(image) 创建一个可以在给定图像上绘图的对象。
draw.text draw.text( (x,y), text, font, color )

t =
0
1
2
3
(60*t + 10, 10)是字体的坐标位置
code.jpg

  • pillow文档

详细了解PIL的强大功能,请请参考Pillow官方文档:
https://pillow.readthedocs.org/

原理

字符画是一系列字符的组合,我们可以把字符看作是比较大块的像素,一个字符能表现一种颜色,字符的种类越多,可以表现的颜色也越多,图片也会更有层次感。

先将图片转为灰度值
灰度值公式: 0.2126 r + 0.7152 g + 0.0722 b 0.2126 r + 0.7152 g + 0.0722 * b
再用一个字符能表现一种颜色
$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`’.
不同灰度对应不同字符,最后输出字符即可
return ascii_char[int(gray / unit)]

代码实现

from PIL import Image
import argparse

# 命令行输入参数处理
parser = argparse.ArgumentParser()

parser.add_argument('--width', type=int, default=80)  # 输出字符画宽
parser.add_argument('--height', type=int, default=80)  # 输出字符画高

# 获取参数
args = parser.parse_args()

width = args.width
height = args.height

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")


def get_char(r, g, b, alpha=256):  # alpha透明度
    if alpha == 0:
        return ''
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)  # 计算灰度值
    unit = (256.0 + 1) / length
    return ascii_char[int(gray / unit)]  # 不同灰度对应不同字符


if __name__ == '__main__':
    im = Image.open('wife.jpg')
    im = im.resize((width, height), Image.NEAREST)
    txt = ''
    for i in range(height):
        for j in range(width):
            txt += get_char(*im.getpixel((j, i)))
        txt += '\n'
    print(txt)
    with open("output.txt", 'w') as f:
        f.write(txt)

output.txt

结语

新手1程序媛,跨行转ds,技术不扎实请多包涵
博客中所有文章的目的均是为了记录自己的学习过程而已,所以基本是想到什么写什么,以项目为导向,做的过程中缺什么基础知识就写什么,方便自己以后回顾
缺乏大局逻辑和排版,请见谅

欢迎小白们互相交流与沟通
欢迎大神们鞭策批评与指导


作者: Murphy


  1. 菜鸡的委婉表达方式,指刚上路且车技不好的Rockie ↩︎

猜你喜欢

转载自blog.csdn.net/Weizhiyuan37927/article/details/89395351