为什么我不能在python中挤出一张图片

时间:2015-06-07 15:40:28

标签: image python-2.7

我尝试使用此代码挤压图像:

:*:h::
    SendInput, х
    FingerPrint(22)
    return
:*:s::
    SendInput, с
    FingerPrint(22)
    return

:*:sh::
    SendInput, ш
    FingerPrint(22)
    return

当我在图像上试一试时,它告诉我:

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) 
    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    

我怎样才能让它在两列上都有效?

1 个答案:

答案 0 :(得分:1)

考虑数组的形状。 假设im具有形状(factor*H, factor*W),那么 new_mat的形状为(H, W)

现在考虑一下

new_mat[:,j] = im[:,curr_range].mean(axis=1) 

在右侧,im[:, curr_range]的某些(factor*H, L)的形状为L,而im[:,curr_range].mean(axis=1)的形状为(factor*H,)

在左侧,new_mat[:, j]的形状为(H,)

除了factor = 1时,作业左侧和右侧的形状不匹配,无法广播同意。

此问题会影响squeeze_image两个版本。

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

new_mat[i, j] = im[i*factor:(i+1)*factor, j*factor:(j+1)*factor].mean()

一次切掉im的2D矩形块,然后取2D维修的平均值。

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]]

一位鸽友,但计算这一结果的效率要高得多 使用reshape/swapaxes到形状(factor,factor)的{​​{3}}, 然后取每个块的平均值:

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

速度优势随着squeeze_image中for循环的迭代次数而增加,等于H2*W2

请注意,chop the array into blocks也可以挤压或缩放图像。它使用样条插值而不是采用手段。结果,即使使用样条order=1,也会有所不同:

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

产量

[[  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.  ]]