我有以下代码,
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image as im
B = 9
pic = np.array(im.open('portrait.png'))
pic = pic[pic.shape[0] % B:, pic.shape[1] % B:, :3]
reduced, _i, _j = [], 0, 0
for i in range(B, pic.shape[0] + B, B):
for j in range(B, pic.shape[1] + B, B):
pix = pic[_i:i, _j:j].reshape(B * B, 3).mean(axis=0)
reduced.append(pix.astype(np.uint8))
_j = j
_i, _j = i, 0
reduced = np.array(reduced)
reduced = reduced.reshape((pic.shape[0] // B, pic.shape[1] // B, 3))
plt.title(reduced.shape)
plt.imshow(reduced)
plt.show()
它本质上是通过图像的
B
块迭代B
,并通过取它们的平均值将它们变成一个像素。
所以这个,
变成这样,
我认为这可以通过重塑、沿某个轴取平均值然后再次重塑来以某种方式完成。但我不确定如何取出那个循环。
您可以在图像中引入
BxB
块作为额外的轴,然后沿这些轴取平均值:
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image as im
B = 9
pic = np.array(im.open('portrait.png'))
h, w, c = pic.shape
H, W = h - h % B, w - w % B
reduced = (
pic[-H:,-W:] # crop to multiple of block size
.reshape((H // B, B, W // B, B, c)) # split y and x axes into blocks
.mean(axis=(1,3)) # take the mean
.astype(np.uint8) # convert from float
)
plt.title(reduced.shape)
plt.imshow(reduced)
plt.show()
einops
以直接且不言自明的方式实现它,如下所示:
import einops
img = ...
B=9
im_reduced = einops.reduce(img, "(h Bh) (w Bw) C -> h w C", "mean", Bh=B, Bw=B)