Image 为什么可以';我不能用python压缩一张图片吗

Image 为什么可以';我不能用python压缩一张图片吗,image,python-2.7,Image,Python 2.7,我尝试使用以下代码压缩图像: def squeeze_image(im,factor): new_n = im.shape[0]/ factor new_m = im.shape[1]/factor new_mat = np.zeros((new_n,new_m)) for j in range(new_mat.shape[1]): curr_range = range(j*factor,min((j+1)*factor,im.shape[1])

我尝试使用以下代码压缩图像:

def squeeze_image(im,factor):
    new_n = im.shape[0]/ factor
    new_m = im.shape[1]/factor
    new_mat = np.zeros((new_n,new_m)) 
    for j in range(new_mat.shape[1]):
        curr_range = range(j*factor,min((j+1)*factor,im.shape[1])) 
        new_mat[:,j] = im[:,curr_range].mean(axis=1) 
    for i in range(new_mat.shape[0]):
        curr_range1 = range(i*factor,min((i+1)*factor,im.shape[0])) 
        new_mat[i,:] = im[curr_range1,:].mean(axis=0)           
    return new_mat    
当我在图像上尝试时,它告诉我:

ValueError:无法将输入数组从形状(512)广播到形状(256)

出于某种原因,它只在我只对行或列使用它时才起作用, 像这样:

def squeeze_image(im,factor):
    new_n = im.shape[0]/ factor
    new_m = im.shape[1]/factor
    new_mat = np.zeros((new_n,new_m)) 
    for j in range(new_mat.shape[1]):
        curr_range = range(j*factor,min((j+1)*factor,im.shape[1])) 
        new_mat[:,j] = im[:,curr_range].mean(axis=1) 
    return mat

如何使它同时适用于行和列?

考虑数组的形状。 假设
im
具有形状
(因子*H,因子*W)
,那么
new\u mat
具有形状
(H,W)

现在考虑线

new_mat[:,j] = im[:,curr_range].mean(axis=1) 
在右侧,
im[:,curr\u range]
具有形状
(系数*H,L)
对于某些
L
,和
im[:,curr\u range]。平均值(轴=1)
具有形状
(系数*H,)

在左侧,
new_mat[:,j]
具有形状
(H,)

因此,除了当
factor=1
时,赋值的左侧和右侧的形状不匹配,无法广播以使其一致

此问题影响两个版本的
压缩图像

要解决此问题,您可以使用

new_mat[i, j] = im[i*factor:(i+1)*factor, j*factor:(j+1)*factor].mean()
一次切下
im
的二维矩形面片,并取该二维面片的平均值

import numpy as np
import itertools as IT

def squeeze_image(im,factor):
    H, W = im.shape
    H2, W2 = H/factor, W/factor
    new_mat = np.zeros((H2, W2)) 
    for i, j in IT.product(range(H2), range(W2)):
        new_mat[i, j] = im[i*factor:(i+1)*factor, j*factor:(j+1)*factor].mean()
    return new_mat

im = np.arange(100).reshape((10,10))
print(im)
# [[  0.   1.   2.   3.   4.   5.   6.   7.   8.   9.]
#  [ 10.  11.  12.  13.  14.  15.  16.  17.  18.  19.]
#  [ 20.  21.  22.  23.  24.  25.  26.  27.  28.  29.]
#  [ 30.  31.  32.  33.  34.  35.  36.  37.  38.  39.]
#  [ 40.  41.  42.  43.  44.  45.  46.  47.  48.  49.]
#  [ 50.  51.  52.  53.  54.  55.  56.  57.  58.  59.]
#  [ 60.  61.  62.  63.  64.  65.  66.  67.  68.  69.]
#  [ 70.  71.  72.  73.  74.  75.  76.  77.  78.  79.]
#  [ 80.  81.  82.  83.  84.  85.  86.  87.  88.  89.]
#  [ 90.  91.  92.  93.  94.  95.  96.  97.  98.  99.]]
im2 = squeeze_image(im, 2)
print(im2)
屈服

[[  5.5   7.5   9.5  11.5  13.5]
 [ 25.5  27.5  29.5  31.5  33.5]
 [ 45.5  47.5  49.5  51.5  53.5]
 [ 65.5  67.5  69.5  71.5  73.5]
 [ 85.5  87.5  89.5  91.5  93.5]]
[[  0.     2.25   4.5    6.75   9.  ]
 [ 22.5   24.75  27.    29.25  31.5 ]
 [ 45.    47.25  49.5   51.75  54.  ]
 [ 67.5   69.75  72.    74.25  76.5 ]
 [ 90.    92.25  94.5   96.75  99.  ]]

计算这一结果的一种更奇特但更有效的方法是 使用
重塑/swapaxes
来改变形状
(系数,系数)
, 然后取每个块的平均值:

def downsample(im,factor):
    H, W = im.shape
    H2, W2 = H/factor, W/factor
    im = im[:H2*factor, :W2*factor]
    new_mat = (im.reshape(H2, factor, -1, factor)
               .swapaxes(1, 2)).reshape(H2, W2, -1).mean(axis=-1)
    return new_mat
对于小型阵列
im
,这大约快17倍

In [91]: %timeit squeeze_image(im, 2)
1000 loops, best of 3: 319 µs per loop

In [97]: %timeit downsample(im, 2)
100000 loops, best of 3: 17.2 µs per loop
速度优势随着
压缩_image
中for循环的迭代次数增加而增加,这等于
H2*W2


请注意,也可以压缩或缩放图像。它使用样条插值,而不是采用平均值。但是,即使使用样条曲线
顺序=1
,结果也有点不同:

import scipy.ndimage as ndimage
print(ndimage.zoom(im, 0.5, order=1))
屈服

[[  5.5   7.5   9.5  11.5  13.5]
 [ 25.5  27.5  29.5  31.5  33.5]
 [ 45.5  47.5  49.5  51.5  53.5]
 [ 65.5  67.5  69.5  71.5  73.5]
 [ 85.5  87.5  89.5  91.5  93.5]]
[[  0.     2.25   4.5    6.75   9.  ]
 [ 22.5   24.75  27.    29.25  31.5 ]
 [ 45.    47.25  49.5   51.75  54.  ]
 [ 67.5   69.75  72.    74.25  76.5 ]
 [ 90.    92.25  94.5   96.75  99.  ]]