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