这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题
于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。
微信小程序搜索:Python面试宝典
或可关注原创个人博客:https://lienze.tech
也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习
0~255
,白色为255
,黑色为0
,所以黑白图片也被成为灰度图像每一个灰度值,我们都会有对应的ascii字符与之对应,通过字符所占空间大小,来确定其亮度,越靠前的,那么灰度值越低,也就越暗
灰度值计算公式:0.299 * R
+ 0.587 * G
+ 0.144 * B
def gray2char(r, g, b, alpha=256): ''' 根据RGBA值进行灰度值计算,并返回对应亮度的字符 ''' _ = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") char_length = len(_) # 字符序列长度 proportion = 255 / char_length # 总灰度值对应列表索引范围 gray = 0.2126 * r + 0.7152 * g + 0.0722 * b # 灰度值与rgb的计算公式 return _[int(gray / proportion) - 1] # 返回当前灰度值所对应字符
通过解析图像,我们可以得处图像每处像素点的rgb颜色值,并且通过这色值对应转化出灰度值,利用灰度值字符函数,将这个像素对应的字符拿到
注意由于字符和像素的宽高是有区别的,一个字符要比一个字符大的多,所以一张图像在处理过程中,宽高首先要进行比例划算,一般一个字符的宽高对于一个像素来说是6:1、11:1
def image2text(path): ''' 对图像进行解析 @path: 图像路径 ''' img = Image.open(path).convert('RGB') # 打开图像 pic_width, pic_height = img.width, img.height # 图像原始宽高 width, height = int(pic_width / 6), int(pic_height / 11) # 字符像素宽高转化 img = img.resize((width, height), Image.NEAREST) # 原始图像进行缩略,适合字符处理 # 像素遍历,进行灰度值字符转化 content = '' # 存储转化结果字符 colors = [] # 对应坐标原始颜色,为了之后给字符上色使用 for h in range(height): # 从高开始 for w in range(width): # 遍历每一行像素 px = img.getpixel((w, h)) # 获取某一点的像素值 char = gray2char(px[0], px[1], px[2], px[3] if len(px) > 3 else 256) colors.append((px[0], px[1], px[2])) content += char content += '\n' # 每一行像素换行追加\n colors.append((255, 255, 255)) # 给换行未来的颜色就是白色 return content, colors, pic_width, pic_height
通过上一步方法,得到的content返回值,正式接下来需要存储如图片的字符内容,这里需要开启一个新的图像对象
结合对应颜色,将字符写入对应的像素点上,最后存储为图片,格式可以是jpg,这样比较小一些,png质量高,结果会大
def text2image(content, colors, pic_width, pic_height, path): ''' 字符存储为图像 @path: 存储路径 ''' image = Image.new("RGB", (pic_width, pic_height), (255, 255, 255)) # 创建存储图像对象 canvas = ImageDraw.Draw(image) # 创建一个支持绘制的画布 font = ImageFont.load_default().font # 直接使用默认字体对象 x = 0 y = 0 font_w, font_h = font.getsize(content[1]) # 字体的宽高 for i in range(len(content)): # 遍历字符内容对象 if content[i] == '\n': # 遍历到\n那就是下一行的元素了 x = -font_w # 每次初始化横纵坐标 y += font_h continue canvas.text((x, y), content[i], colors[i]) # 写入字符,带上颜色 x += font_w # 偏移一个字体的像素 image.save(path)
对一张基本图像进行字符转化,并将结果存储为char.jpg
from PIL import Image, ImageFont, ImageDraw def main(): content, colors, pic_width, pic_height = image2text(path="test.jpg") text2image(content, colors, pic_width, pic_height, path="char.jpg")
如果需要处理的是一个gif图像对象,那么首先将gif图像对象中的每一帧图片单独保存下来,接着图像解析为字符
接着将灰度字符转图片,最后再将字符图像组合为一个gif即可
def gif2image(path): ''' gif图像拆分,并将拆分结果存储当前工作目录下的temp目录中 @path: gif图像位置 ''' img = Image.open(path) work_path = os.getcwd() # 当前工作路径 cache_dir = os.path.join(work_path, 'gifTemp') if not os.path.exists(cache_dir): # 如果不存在保存单独每一帧图片的目录,则创建该目录 os.mkdir(cache_dir) while True: try: current = img.tell() # 获取当前帧位置 file_name = os.path.join(cache_dir, str(current)+'.png') img.save(file_name) img.seek(current+1) # 向下一帧读取 except EOFError: # GIF读取完毕 break return current
之后即可通过for循环使用上面的图像处理的两个方法对其进行处理,处理完成的图像可以保存至content目录下
通过遍历content目录下的处理好的字符图片,对其进行gif拼接
import imageio def image2gif(_id, dir_name='content', duration=15 / 130): ''' 将之前处理好的字符png图片组合成GIF图像 通过imageio模块处理合并 ''' path = os.path.join(os.getcwd(), dir_name) images = [] for pic_id in range(_id): # 遍历取出每一张处理后的字符图片id值 images.append(imageio.imread(os.path.join(path, '%d.png' % pic_id))) # 从文件中读入数据 imageio.mimsave(os.path.join(os.getcwd(), 'fin.gif'), images, duration=duration)