小侠客们好呀,我是oubahe。今天是“好技巧”专题的第4文,来一起看看在实际深度学习项目中遇到的一个难题——利用matplotlib自定义生成的图像如何保存为数组对象,这样图像转化为像素数组之后才能进行一系列的卷积池化等操作。这部分解决方法相关资料非常稀少,也是小编我参考matplotlib和其他包的官方文档来摸索总结的。来吧,展示~
01
—
问题描述
例如,这里通过生成三组随机数来绘制一个自定义的等高线图,具体绘制步骤如下:
import matplotlib.pyplot as pltimport numpy as npx = np.random.random(10)*255y = np.random.random(10)*255z = [np.random.random(len(x))*255 for _ in range(len(y))]fig = plt.figure(figsize = (3.2, 3.2)) # 创建figure对象plt.contourf(param1, param2, param3, cmap = 'brg', vmax = vmax, vmin = vmin)plt.xlabel("x"); plt.ylabel("y")plt.show()
绘制出来带有刻度和轴标签如下图所示。
那么我们如何将这个自定义的图像转化为像素数组呢!?
02
—
解决方法
第1步,将画布上的图像轴标签、网格、刻度等属性删去,使得画布上显示的是纯图像;
第2步,将画布上纯图像四周的白边删除,获取完整的自定义纯图像;
第3步,通过图像对象fig的canvas属性得到图像输出流;
第4步,利用io包的BytesIO属性来创建输入输出流对象buffer读取图像输出流;
第5步,将自定义纯图像的输出流打印到输入输出流对象上;
第6步,通过输入输出流对象的getvalue属性来获取图像输出流的值data;
第7步,借助输入输出流buffer的write属性将像素数据data写入buffer;
第8步,导入PIL包中的Iamge方法,打开buffer中的图像输出流数据保存为PIL.PngImagePlugin.PngImageFile类型的对象img;
第9步,导入numpy包中的asarray方法将img转化为像素数组img_array;
通过上述共9个步骤,下图所示的自定义纯图像便可以顺利地转化为对应的像素数组。需要说的是,由于数据为随机生成,纯图像部分与上图是不一致的。
03
—
实现流程
matplotlib自定义图像保存为数组的具体实现流程如下:
import matplotlib.pyplot as pltfrom PIL import Imageimport numpy as npimport iox = np.random.random(10)*255y = np.random.random(10)*255z = [np.random.random(len(x))*255 for _ in range(len(y))]# 创建figure对象fig = plt.figure(figsize = (3.2, 3.2))# 绘制自定义等高线图 plt.contourf(x, y, z, cmap='brg', vmax=255, vmin=0)# 将图像中其他属性删去plt.axis('off'); plt.xticks([]); plt.yticks([]); plt.margins(0, 0)# 消除纯图像四周白边plt.subplots_adjust(top=1,bottom=0,right=1,left=0,hspace=0,wspace=0) # 读取频谱图输出流canvas = fig.canvas # 创建输入输出流对象 buffer = io.BytesIO() # 将画布上的内容打印到输入输出流对象 canvas.print_png(buffer) # 获取输出流的值 data = buffer.getvalue() # 将数据写入buffer buffer.write(data) # 使用Image打开图片输出流数据 img = Image.open(buffer) # 将img对象转化为像素数组img_array = np.asarray(img)
04
—
结语
上述就是matplotlib自定义图像保存为像素数组的具体方法与实现流程,你学废了吗!?这个小技巧在实际的图像项目开发中威力巨大,若不采用该方法的话,从大批量生成图像,到图像存储为图片落盘,再到从磁盘或云上读取图片为像素数组这一流程所耗费的时间与资源与我们的方法相比可是指数级倍增的。好啦,学习的时间总是那么短暂。我是oubahe,下次再见叻~