打印机模拟(彩色篇)
继承上篇
本来不打算做彩色版的了,毕竟按我的想法和做灰色版的套路是一样的。但是突然又很想看看做出来的效果怎样,和灰度版的对比起来会怎样,所以就对上一份代码修修改改又做出了这版。至于赘言,上一篇里就有了。
做法就基本和上篇灰度版的一样了,都不涉及任何算法,只靠for循环堆砌,毕竟还不是很摸得清python的API用法(刚入门),所以效率很低(当然,python本身效率也是问题啦)。但是目的也只是模拟打印机的工作原理外加满足一下自己的好奇心。先说明这个代码运行起来很慢,扩展2*2都要等上十秒左右,有耐心再试。
效果
从上往下从左往右分别就是2*2、3*3、4*4和原图了。可以拿上篇的灰度图对比一下,做到4*4的时候效果还远远没有这次的好。但毕竟这是彩色的,本身RGB就是灰色的三倍大小了,猜一下就知道这次的视觉效果会更佳。但随之而来的必然是更大的空间和时间的消耗。
python代码
实现基本和上一篇灰度版的差不多方法,都很丑陋且低效,运行起来能听到本子CPU风扇的轰鸣声。
from PIL import Image
from numpy import *
from pylab import *
import numpy as npfilename = 'test.jpg';
im = Image.open(filename);
width, height = im.size;r, g, b = im.split();
r_arr = np.array(r).reshape(height, width);
g_arr = np.array(g).reshape(height, width);
b_arr = np.array(b).reshape(height, width);dim = 4;#2, 3 or 4
if dim == 2:paint = [[0, 2], [3, 1]];
elif dim == 3:paint = [[0, 7, 2], [8, 4, 5], [3, 6, 1]];
elif dim == 4:paint = [[0, 8, 2, 10], [12,4,14,6], [3,11,1,9],[15,7,13,5]];top_color = 255;
new_r_arr = [None] * (dim * height);
new_g_arr = [None] * (dim * height);
new_b_arr = [None] * (dim * height);
for i in range(dim * height):new_r_arr[i] = [0] * (dim * width);new_g_arr[i] = [0] * (dim * width);new_b_arr[i] = [0] * (dim * width);div = top_color / (dim * dim);
for i in range(0, height):for j in range(0, width):r_tmp = int(r_arr[i][j] / div);g_tmp = int(g_arr[i][j] / div);b_tmp = int(b_arr[i][j] / div);for ii in range(0, dim):for jj in range(0, dim):if paint[ii][jj] < r_tmp:new_r_arr[dim * i + ii][dim * j + jj] = top_color;else :new_r_arr[dim * i + ii][dim * j + jj] = 0;if paint[ii][jj] < g_tmp:new_g_arr[dim * i + ii][dim * j + jj] = top_color;else :new_g_arr[dim * i + ii][dim * j + jj] = 0;if paint[ii][jj] < b_tmp:new_b_arr[dim * i + ii][dim * j + jj] = top_color;else :new_b_arr[dim * i + ii][dim * j + jj] = 0;im_arr = np.dstack((new_r_arr, new_g_arr, new_b_arr));
new_im = Image.fromarray(np.uint8(im_arr));
new_im.show();
注意
倒数第二行的这句里要显式的将im_arr转成uint8,不然会报 TypeError: Cannot handle this data type。这点我一开始根本不知道,被卡了好一会,然后才误打误撞的在stackoverflow上别人回答的其它的问题上发现这样能解决。至于为什么我也没搞清,大概还是python对数据类型比较严格吧。
new_im = Image.fromarray(np.uint8(im_arr));