我想拍摄图像并改变图像的比例,而它是一个numpy数组。
例如,我有一个可口可乐瓶的图像: bottle-1
哪个转换为形状(528, 203, 3)
的numpy数组,我想调整大小以表示第二个图像的大小:
bottle-2
其形状为(140, 54, 3)
。
如何在保持原始图像的同时将图像尺寸更改为特定形状?其他答案建议剥离所有其他或第三行,但我想要做的是基本上缩小图像如何通过图像编辑器,但在python代码。是否有任何库可以在numpy / SciPy中执行此操作?
答案 0 :(得分:56)
是的,您可以安装opencv
(这是一个用于图像处理和计算机视觉的库),并使用cv2.resize
功能。例如使用:
import cv2
import numpy as np
img = cv2.imread('your_image.jpg')
res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)
因此img
是一个包含原始图像的numpy数组,而res
是一个包含 resized 图像的numpy数组。一个重要的方面是interpolation
参数:有几种方法可以调整图像大小。特别是因为缩小图像,原始图像的大小不是调整大小后图像大小的倍数。可能的插值模式是:
INTER_NEAREST
- 最近邻插值INTER_LINEAR
- 双线性插值(默认使用)INTER_AREA
- 使用像素区域关系重新采样。它可能是图像抽取的首选方法,因为它不会产生莫尔条纹 结果。但是当图像被缩放时,它就像是INTER_NEAREST
方法。INTER_CUBIC
- 4x4像素邻域的双三次插值INTER_LANCZOS4
- 8x8像素邻域的Lanczos插值
与大多数选项一样,没有“最佳”选项,因为对于每个调整大小架构,都有一种策略可以优先于另一种策略。
答案 1 :(得分:31)
虽然可以单独使用numpy来执行此操作,但操作不是内置的。也就是说,你可以使用scikit-image
(建立在numpy上)来进行这种图像处理。
Scikit-Image重新缩放文档为here。
例如,您可以对图片执行以下操作:
from skimage.transform import resize
bottle_resized = resize(bottle, (140, 54), anti_aliasing=True)
这将为您处理插值,消除锯齿等问题。
答案 2 :(得分:4)
SciPy的# inside views.py
from .custom_serializer import CustomSerializer
def employee(request):
...
json_data = CustomSerializer().serialize(
entries
fields = (
'First_Name',
'email'
)
方法是另一种调整大小的方法,但是将从SciPy v 1.3.0开始将其删除。 SciPy指的是 PIL 图像调整大小方法:imresize()
尺寸 –请求的尺寸(以像素为单位),以2元组表示:(宽度,高度)。
重采样 –可选的重采样过滤器。这可以是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
答案 3 :(得分:1)
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)
答案 4 :(得分:1)
对于想要调整(插值)一批numpy数组的人,pytorch提供了一个更快的函数名torch.nn.functional.interpolate,记得先使用np.transpose将通道从batchxWxHx3改为batchx3xWxH。
答案 5 :(得分:0)
对于来自Google来这里的人们,他们正在寻找一种快速的方法来对numpy
数组中的图像进行下采样以用于机器学习应用程序,这是一种超级快速的方法(改编自here)。此方法仅在输入尺寸为输出尺寸的倍数时有效。
以下示例将采样率从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)
此方法使用的是最大池化。我发现这是最快的方法。
答案 6 :(得分:0)
在numpy / SciPy中是否有任何库可以做到这一点
好的。您可以在没有OpenCV,scikit-image或PIL的情况下执行此操作。
图像调整大小基本上是将原始图像中每个像素的坐标映射到其调整大小的位置。
由于图像的坐标必须是整数(将其视为矩阵),所以如果映射的坐标具有十进制值,则应插值像素值以使其接近整数位置(例如,获取与该像素最近的像素)位置称为Nearest neighbor interpolation)。
您所需要做的就是为您执行此插值的功能。 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))
当然,如果您的图像是RGB,则必须对每个通道执行插值。
如果您想了解更多信息,建议您观看Resizing Images - Computerphile。
答案 7 :(得分:0)
如果有人来这里寻找一种简单的方法来在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数组配合使用。
答案 8 :(得分:0)
对于基本的下采样(按2)的简单的单行numpy解决方案:
smaller_img = bigger_img[::2, ::2]
和上采样(按2):
bigger_img = smaller_img.repeat(2, axis=0).repeat(2, axis=1)
(这是将HxWxC形状的图像假定为L.Kärkkäinen的h / t)