是的,你可以安装opencv
(这是一个用于图像处理和计算机视觉的库),并使用cv2.resize
函数。例如使用:
import cv2
import numpy as np
img = cv2.imread('your_image.jpg')
res = <b>cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)</b>
在这里img
是一个包含原始图像的numpy数组,而res
是一个包含调整大小后图像的numpy数组。一个重要的方面是interpolation
参数:有几种方法可以调整图像大小,特别是当你缩小图像并且原始图像的尺寸不是调整后图像尺寸的倍数时。可能的插值模式有:
INTER_NEAREST
- 最近邻插值INTER_LINEAR
- 双线性插值(默认使用)INTER_AREA
- 使用像素区域关系重新采样。这可能是图像缩减的首选方法,因为它提供了无莫尔纹的结果。但是当图像被缩放时,它类似于INTER_NEAREST
方法。INTER_CUBIC
- 在4x4像素邻域上进行双三次插值INTER_LANCZOS4
- 在8x8像素邻域上进行Lanczos插值
与大多数选项一样,没有“最佳”选项,因为对于每个调整大小方案,都有一些情况下可以优先选择一种策略。
dsize
应该为dsize=(54, 140)
,因为它按照x和y的顺序进行调整大小,而numpy数组的形状是y然后x(y是行数,x是列数)。 - Brian Hamillskimage.io.imread('image.jpg')
和skimage.transform.resize(img)
。https://scikit-image.org/docs/dev/install.html - Eduardo Pignatelli虽然可能可以仅使用numpy来完成此操作,但该操作不是内置的。话虽如此,您可以使用基于numpy构建的scikit-image
来进行这种类型的图像处理。
Scikit-Image缩放文档在此处。
例如,您可以对图像执行以下操作:
from skimage.transform import resize
bottle_resized = resize(bottle, (140, 54))
这将为您处理插值、抗锯齿等问题。
一行numpy代码实现下采样(降采样)(2倍):
smaller_img = bigger_img[::2, ::2]
并且进行上采样(增加采样率)(倍数为2):
bigger_img = smaller_img.repeat(2, axis=0).repeat(2, axis=1)
(假设图片大小为HxWxC。请注意,此方法仅允许整数倍缩放(例如2倍,但不支持1.5倍))
np.kron(..., np.ones((2,2,1)))
(对于 HxWxC
图像),但我不确定哪个更快。 - flawr如果您从Google来到这里,寻找一种在numpy数组中快速降采样图像以用于机器学习应用的方法,这里有一个超级快的方法(改编自这里)。该方法仅在输入维度为输出维度的倍数时有效。
以下示例从128x128降采样到64x64(这可以轻松更改)。
通道最后排序
# large image is shape (128, 128, 3)
# small image is shape (64, 64, 3)
input_size = 128
output_size = 64
bin_size = input_size // output_size
small_image = large_image.reshape((output_size, bin_size,
output_size, bin_size, 3)).max(3).max(1)
通道优先排序
# large image is shape (3, 128, 128)
# small image is shape (3, 64, 64)
input_size = 128
output_size = 64
bin_size = input_size // output_size
small_image = large_image.reshape((3, output_size, bin_size,
output_size, bin_size)).max(4).max(2)
对于灰度图像,只需将3
更改为1
,如下所示:
通道优先排序
# large image is shape (1, 128, 128)
# small image is shape (1, 64, 64)
input_size = 128
output_size = 64
bin_size = input_size // output_size
small_image = large_image.reshape((1, output_size, bin_size,
output_size, bin_size)).max(4).max(2)
这种方法使用了等效的最大池化技术,这是我发现的最快速的做法。
np.repeat(np.repeat(a, 2, axis=0), 2, axis=1)
。 - Tronic.max(4).max(2)
替换为.mean(4).mean(2)
是否可以作为一种快速的线性插值下采样方法? - HockeyStick如果有人在这里寻找一个简单的方法来缩放/调整Python中的图像大小,而不使用额外的库,那么这里有一个非常简单的图像大小调整函数:
#simple image scaling to (nR x nC) size
def scale(im, nR, nC):
nR0 = len(im) # source number of rows
nC0 = len(im[0]) # source number of columns
return [[ im[int(nR0 * r / nR)][int(nC0 * c / nC)]
for c in range(nC)] for r in range(nR)]
示例用法:将 (30 x 30) 的图像调整大小为 (100 x 200):
import matplotlib.pyplot as plt
def sqr(x):
return x*x
def f(r, c, nR, nC):
return 1.0 if sqr(c - nC/2) + sqr(r - nR/2) < sqr(nC/4) else 0.0
# a red circle on a canvas of size (nR x nC)
def circ(nR, nC):
return [[ [f(r, c, nR, nC), 0, 0]
for c in range(nC)] for r in range(nR)]
plt.imshow(scale(circ(30, 30), 100, 200))
这可以用来缩小/缩放图像,并且在numpy数组中运行良好。
如果想要批量改变(numpy)数组的大小(插值),pytorch提供了一个更快的函数名为torch.nn.functional.interpolate,只需记得先使用np.transpose将通道从batchxWxHx3更改为batchx3xWxH。
几年后我又回到这里,发现目前的答案可以归为以下几类:
这些解决方案都是可行的,我提供以下内容只是为了完整性。它比以上三种方法有三个优点:(1) 可以接受任意分辨率,甚至非二次幂的缩放因子;(2) 它仅使用纯Python+Numpy,没有使用外部库;(3) 它对所有像素进行插值处理,获得更美观的结果。
它并没有很好地利用Numpy,因此速度不快,特别是对于大图像来说。如果你只需要对较小的图像进行重新缩放,则应该可以接受。我根据用户的自由选择提供Apache或MIT许可证。
import math
import numpy
def resize_linear(image_matrix, new_height:int, new_width:int):
"""Perform a pure-numpy linear-resampled resize of an image."""
output_image = numpy.zeros((new_height, new_width), dtype=image_matrix.dtype)
original_height, original_width = image_matrix.shape
inv_scale_factor_y = original_height/new_height
inv_scale_factor_x = original_width/new_width
# This is an ugly serial operation.
for new_y in range(new_height):
for new_x in range(new_width):
# If you had a color image, you could repeat this with all channels here.
# Find sub-pixels data:
old_x = new_x * inv_scale_factor_x
old_y = new_y * inv_scale_factor_y
x_fraction = old_x - math.floor(old_x)
y_fraction = old_y - math.floor(old_y)
# Sample four neighboring pixels:
left_upper = image_matrix[math.floor(old_y), math.floor(old_x)]
right_upper = image_matrix[math.floor(old_y), min(image_matrix.shape[1] - 1, math.ceil(old_x))]
left_lower = image_matrix[min(image_matrix.shape[0] - 1, math.ceil(old_y)), math.floor(old_x)]
right_lower = image_matrix[min(image_matrix.shape[0] - 1, math.ceil(old_y)), min(image_matrix.shape[1] - 1, math.ceil(old_x))]
# Interpolate horizontally:
blend_top = (right_upper * x_fraction) + (left_upper * (1.0 - x_fraction))
blend_bottom = (right_lower * x_fraction) + (left_lower * (1.0 - x_fraction))
# Interpolate vertically:
final_blend = (blend_top * y_fraction) + (blend_bottom * (1.0 - y_fraction))
output_image[new_y, new_x] = final_blend
return output_image
示例重新缩放:
SciPy的imresize()
方法是另一种调整大小的方法,但它将从SciPy v 1.3.0开始被移除。SciPy使用PIL图像调整大小方法:Image.resize(size, resample=0)
size - 请求的像素大小,作为2元组:(宽度,高度)。
resample - 可选的重采样滤波器。这可以是以下其中之一:PIL.Image.NEAREST(使用最近邻),PIL.Image.BILINEAR(线性插值),PIL.Image.BICUBIC(三次样条插值)或PIL.Image.LANCZOS(高质量降采样滤波器)。如果省略或图像具有模式“1”或“P”,则设置为PIL.Image.NEAREST。
链接在此处: https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize
有没有numpy / SciPy中的库可以做到这一点
当然可以。您可以不使用OpenCV,scikit-image或PIL来完成此操作。
图像调整基本上是将每个像素的坐标从原始图像映射到其调整后的位置。
由于图像的坐标必须是整数(将其视为矩阵),因此,如果映射的坐标具有小数值,则应对像素值进行插值以将其近似到整数位置(例如,获取最接近该位置的像素称为最近邻插值)。
您所需要的就是一个为您执行此插值的函数。SciPy有interpolate.interp2d
。
您可以使用它来调整numpy数组中的图像,例如arr
:
W, H = arr.shape[:2]
new_W, new_H = (600,300)
xrange = lambda x: np.linspace(0, 1, x)
f = interp2d(xrange(W), xrange(H), arr, kind="linear")
new_arr = f(xrange(new_W), xrange(new_H))
import cv2
import numpy as np
image_read = cv2.imread('filename.jpg',0)
original_image = np.asarray(image_read)
width , height = 452,452
resize_image = np.zeros(shape=(width,height))
for W in range(width):
for H in range(height):
new_width = int( W * original_image.shape[0] / width )
new_height = int( H * original_image.shape[1] / height )
resize_image[W][H] = original_image[new_width][new_height]
print("Resized image size : " , resize_image.shape)
cv2.imshow(resize_image)
cv2.waitKey(0)
cv2
和适当的调整大小函数的现有答案有什么价值,而你重新实现了一个次优的调整大小函数,其表现不如最近邻插值。 - NOhs