这是一个我在博客园也写了的文章,很简单的一个小程序,涉及到python的matplotlib的画布转图片保存,以及控制图像大小的一些问题。
近期在B站答应了帮人切割一匹像素游戏图片:
![](https://img-blog.csdnimg.cn/img_convert/3d0704e02c5c38ea247cc547db76270f.png)
这是一张PNG图,我需要将图中的独立的图像帧切割成一样大小,同事保证图像要在中间。
还好,图片之间挺规律的,使用熟悉的Python处理一下应该可以我的想法是这样的:
先删除掉整行整列,得到一个图像紧凑的图片。
PNG图片在程序里打开居然是RPG像素点和灰度值,这个倒是在我的知识之外。
对整行整列进行判断,在网上查了一下,使用线性代数的奇异值比较好。
奇异值是将一个大的矩阵用三个小矩阵表示:
from PIL import Image
import numpy as np
import os
folder_url = './'
file_list = os.listdir(folder_url)
pic = np.array(Image.open(folder_url + file_list[0]))
pic = pic[0:120,0:120]
print(pic.shape)
col = pic[:,0]
print(col)
u, s, vh = np.linalg.svd(col)
print(s)
这个是输出:
(120, 120, 4)
[[255 255 255 0]
[255 255 255 0]
[255 255 255 0]
...
[255 255 255 0]
[255 255 255 0]]
[4.83828482e+03 6.69772121e-13 3.66435383e-29 0.00000000e+00]
其实写到这里的时候就卡住了,将图像中空白的行和列删除的代还没没写出来,我就看到了这种图片:
![](https://img-blog.csdnimg.cn/img_convert/a662420a98dc6d065218ffad956badee.png)
这种技能特效在图像中进项上面所说的切割的话肯定会被破坏掉,所以只能手动切割了,还要计算图像的大小。
最后的程序用了TensorFlow进行数据切割,将大的PNG数据切割成小块的张量数组,使用的matplotlib的画布来保存。
我本来也想用OpenCV,Bug多多放弃了,因为保存的PNG小图像帧有条纹背景!
import tensorflow as tf
import matplotlib.pyplot as plt
import os
folder_url = './'
file_list = os.listdir(folder_url)
print(file_list)
#保存路径
min_pic_name = file_list[0].split('.')[0]
save_url= './Pic-ed/' + min_pic_name + '/'
#读取图像
pic1_data = tf.io.read_file(folder_url + file_list[0])
pic_tensor = tf.image.decode_png(pic1_data)
#图像裁切,因为图像数据不统一,这里只能手动设置
pic_tensor = pic_tensor[11:1011,0:700]
#设置画板样式
plt.figure(figsize=(8,8))
plt.box(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.gca().axes.get_xaxis().set_visible(False)
pic_list = []
h = pic_tensor.shape[0]
w = pic_tensor.shape[1]
min_w = 100 #图像宽度
min_h = 100 #图像高度
for x in range(0, int(w/min_w)):
temp_list = []
pic_col = pic_tensor[:, x*min_w:(x+1)*min_w] #取一列图像
for y in range(0, int(h/min_h)):
min_pic = pic_col[y*min_h:(y+1)*min_h, :] #取一小张图像
plt.imshow(min_pic) #绘制在画布上
temp_list.append(min_pic)
#保存图像,这里可以设置图像的质量
plt.savefig(save_url + min_pic_name +"{}.png".format(str(x+1) + '_' + str(y+1)),transparent=True) #清除画板内容
plt.clf()
#重新设置画板样式
plt.box(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.gca().axes.get_xaxis().set_visible(False)
pic_list.append(temp_list)
其实又渣又烂的程序,还有bug……
这是切割后的效果:
![](https://img-blog.csdnimg.cn/img_convert/33244173fab0938783181561ac826c23.png)
没做过游戏,看到这些一帧帧的刷动画动起来还是挺惊艳的。