如何 deform/scale 一维的 3 维 numpy 数组?
How to deform/scale a 3 dimensional numpy array in one dimension?
我想deform/scale一个一维的三维numpy数组。我将在 2D 中可视化我的问题:
我有原始图像,它是一个二维 numpy 数组:
然后我想 deform/scale 它用于维度 0 或水平维度中的某些因素:
对于 PIL images, there are a lot of solutions, for example in pytorch,但是如果我有一个 numpy 形状数组 (w, h, d) = (288, 288, 468) 怎么办?我想以 1.04 的因子对宽度进行上采样,例如,到 (299, 288, 468)。每个单元格包含一个介于 0 和 1 之间的标准化数字。
我不确定,如果我只是没有在寻找正确的词汇,如果我尝试在线搜索。因此,纠正我的问题也会有所帮助。或者告诉我这个问题的数学背景,我可以自己写代码。
谢谢!
您可以沿特定轴重复数组的次数等于 ceil(factor)
,其中 factor > 1
然后在拉伸维度上均匀 space 索引到 select int(factor * old_length)
个元素。这不执行任何类型的插值,而只是重复一些元素:
import math
import cv2
import numpy as np
from scipy.ndimage import imread
img = imread('/tmp/example.png')
print(img.shape) # (512, 512)
axis = 1
factor = 1.25
stretched = np.repeat(img, math.ceil(factor), axis=axis)
print(stretched.shape) # (512, 1024)
indices = np.linspace(0, stretched.shape[axis] - 1, int(img.shape[axis] * factor))
indices = np.rint(indices).astype(int)
result = np.take(stretched, indices, axis=axis)
print(result.shape) # (512, 640)
cv2.imwrite('/tmp/stretched.png', result)
这是结果(左边是原来的example.png
,右边是stretched.png
):
这是使用 scipy.interpolate
对 3D 图像进行线性上采样的示例,希望对您有所帮助。
(我在这里用 np.meshgrid
工作了很多,如果你不熟悉它,我最近解释了它 )
import numpy as np
import matplotlib.pyplot as plt
import scipy
from scipy.interpolate import RegularGridInterpolator
# should be 1.3.0
print(scipy.__version__)
# =============================================================================
# producing a test image "image3D"
# =============================================================================
def some_function(x,y,z):
# output is a 3D Gaussian with some periodic modification
# its only for testing so this part is not impotent
out = np.sin(2*np.pi*x)*np.cos(np.pi*y)*np.cos(4*np.pi*z)*np.exp(-(x**2+y**2+z**2))
return out
# define a grid to evaluate the function on.
# the dimension of the 3D-Image will be (20,20,20)
N = 20
x = np.linspace(-1,1,N)
y = np.linspace(-1,1,N)
z = np.linspace(-1,1,N)
xx, yy, zz = np.meshgrid(x,y,z,indexing ='ij')
image3D = some_function(xx,yy,zz)
# =============================================================================
# plot the testimage "image3D"
# you will see 5 images that corresponds to the slicing of the
# z-axis similar to your example picture_
# https://sites.google.com/site/linhvtlam2/fl7_ctslices.jpg
# =============================================================================
def plot_slices(image_3d):
f, loax = plt.subplots(1,5,figsize=(15,5))
loax = loax.flatten()
for ii,i in enumerate([8,9,10,11,12]):
loax[ii].imshow(image_3d[:,:,i],vmin=image_3d.min(),vmax=image_3d.max())
plt.show()
plot_slices(image3D)
# =============================================================================
# interpolate the image
# =============================================================================
interpolation_function = RegularGridInterpolator((x, y, z), image3D, method = 'linear')
# =============================================================================
# evaluate at new grid
# =============================================================================
# create the new grid that you want
x_new = np.linspace(-1,1,30)
y_new = np.linspace(-1,1,40)
z_new = np.linspace(-1,1,N)
xx_new, yy_new, zz_new = np.meshgrid(x_new,y_new,z_new,indexing ='ij')
# change the order of the points to match the input shape of the interpolation
# function. That's a bit messy but i couldn't figure out a way around that
evaluation_points = np.rollaxis(np.array([xx_new,yy_new,zz_new]),0,4)
interpolated = interpolation_function(evaluation_points)
plot_slices(interpolated)
原始(20,20,20)
维3D图像:
以及上采样的 (30,40,20)
维 3D 图像:
看起来就像使用 pytorch 中的 torch.nn.functional.interpolate
函数并选择 'trilinear' 作为插值模式一样简单:
import torch
PET = torch.tensor(data)
print("Old shape = {}".format(PET.shape))
scale_factor_x = 1.4
# Scaling.
PET = torch.nn.functional.interpolate(PET.unsqueeze(0).unsqueeze(0),\
scale_factor=(scale_factor_x, 1, 1), mode='trilinear').squeeze().squeeze()
print("New shape = {}".format(PET.shape))
输出:
>>> Old shape = torch.Size([288, 288, 468])
>>> New shape = torch.Size([403, 288, 468])
我通过查看数据验证了结果,但由于数据隐私,我不能在这里展示它们。抱歉!
我想deform/scale一个一维的三维numpy数组。我将在 2D 中可视化我的问题:
我有原始图像,它是一个二维 numpy 数组:
然后我想 deform/scale 它用于维度 0 或水平维度中的某些因素:
对于 PIL images, there are a lot of solutions, for example in pytorch,但是如果我有一个 numpy 形状数组 (w, h, d) = (288, 288, 468) 怎么办?我想以 1.04 的因子对宽度进行上采样,例如,到 (299, 288, 468)。每个单元格包含一个介于 0 和 1 之间的标准化数字。
我不确定,如果我只是没有在寻找正确的词汇,如果我尝试在线搜索。因此,纠正我的问题也会有所帮助。或者告诉我这个问题的数学背景,我可以自己写代码。
谢谢!
您可以沿特定轴重复数组的次数等于 ceil(factor)
,其中 factor > 1
然后在拉伸维度上均匀 space 索引到 select int(factor * old_length)
个元素。这不执行任何类型的插值,而只是重复一些元素:
import math
import cv2
import numpy as np
from scipy.ndimage import imread
img = imread('/tmp/example.png')
print(img.shape) # (512, 512)
axis = 1
factor = 1.25
stretched = np.repeat(img, math.ceil(factor), axis=axis)
print(stretched.shape) # (512, 1024)
indices = np.linspace(0, stretched.shape[axis] - 1, int(img.shape[axis] * factor))
indices = np.rint(indices).astype(int)
result = np.take(stretched, indices, axis=axis)
print(result.shape) # (512, 640)
cv2.imwrite('/tmp/stretched.png', result)
这是结果(左边是原来的example.png
,右边是stretched.png
):
这是使用 scipy.interpolate
对 3D 图像进行线性上采样的示例,希望对您有所帮助。
(我在这里用 np.meshgrid
工作了很多,如果你不熟悉它,我最近解释了它
import numpy as np
import matplotlib.pyplot as plt
import scipy
from scipy.interpolate import RegularGridInterpolator
# should be 1.3.0
print(scipy.__version__)
# =============================================================================
# producing a test image "image3D"
# =============================================================================
def some_function(x,y,z):
# output is a 3D Gaussian with some periodic modification
# its only for testing so this part is not impotent
out = np.sin(2*np.pi*x)*np.cos(np.pi*y)*np.cos(4*np.pi*z)*np.exp(-(x**2+y**2+z**2))
return out
# define a grid to evaluate the function on.
# the dimension of the 3D-Image will be (20,20,20)
N = 20
x = np.linspace(-1,1,N)
y = np.linspace(-1,1,N)
z = np.linspace(-1,1,N)
xx, yy, zz = np.meshgrid(x,y,z,indexing ='ij')
image3D = some_function(xx,yy,zz)
# =============================================================================
# plot the testimage "image3D"
# you will see 5 images that corresponds to the slicing of the
# z-axis similar to your example picture_
# https://sites.google.com/site/linhvtlam2/fl7_ctslices.jpg
# =============================================================================
def plot_slices(image_3d):
f, loax = plt.subplots(1,5,figsize=(15,5))
loax = loax.flatten()
for ii,i in enumerate([8,9,10,11,12]):
loax[ii].imshow(image_3d[:,:,i],vmin=image_3d.min(),vmax=image_3d.max())
plt.show()
plot_slices(image3D)
# =============================================================================
# interpolate the image
# =============================================================================
interpolation_function = RegularGridInterpolator((x, y, z), image3D, method = 'linear')
# =============================================================================
# evaluate at new grid
# =============================================================================
# create the new grid that you want
x_new = np.linspace(-1,1,30)
y_new = np.linspace(-1,1,40)
z_new = np.linspace(-1,1,N)
xx_new, yy_new, zz_new = np.meshgrid(x_new,y_new,z_new,indexing ='ij')
# change the order of the points to match the input shape of the interpolation
# function. That's a bit messy but i couldn't figure out a way around that
evaluation_points = np.rollaxis(np.array([xx_new,yy_new,zz_new]),0,4)
interpolated = interpolation_function(evaluation_points)
plot_slices(interpolated)
原始(20,20,20)
维3D图像:
以及上采样的 (30,40,20)
维 3D 图像:
看起来就像使用 pytorch 中的 torch.nn.functional.interpolate
函数并选择 'trilinear' 作为插值模式一样简单:
import torch
PET = torch.tensor(data)
print("Old shape = {}".format(PET.shape))
scale_factor_x = 1.4
# Scaling.
PET = torch.nn.functional.interpolate(PET.unsqueeze(0).unsqueeze(0),\
scale_factor=(scale_factor_x, 1, 1), mode='trilinear').squeeze().squeeze()
print("New shape = {}".format(PET.shape))
输出:
>>> Old shape = torch.Size([288, 288, 468])
>>> New shape = torch.Size([403, 288, 468])
我通过查看数据验证了结果,但由于数据隐私,我不能在这里展示它们。抱歉!