什么是最好的脚本在python中复制matlabs imresize3?



我正在将代码从MATLAB翻译为python,但无法完美地复制MATLAB的imresize3的结果。我的输入是一个101x101x101数组。前四个输入([0,0:3,0]或(1,1:4,1))是:0.3819 0.4033 0.4336 0.2767。两种语言的数据输入是相同的。

sampleQDNormSmall = imresize3(sampleQDNorm,0.5);

结果是一个51x51x51数组,其中前四个值(1,1:4,1)为:0.3443 0.2646 0.2700 0.2835

现在我尝试了两段不同的python代码来复制这些结果:
from skimage.transform import resize
from skimage.transform import rescale
sampleQDNormSmall = resize(sampleQDNorm,(0.5*sampleQDNorm.shape[0],0.5*sampleQDNorm.shape[1],0.5*sampleQDNorm.shape[2]),order=3,anti_aliasing=True);
sampleQDNormSmall1=rescale(sampleQDNorm,0.5,order=3,anti_aliasing=True)

第一个给出了一个51x51x51数组,它的前四个值[0,0:3,0]为:0.3452 0.2669 0.2774 0.3099。这非常接近,但不是完全相同的数值输出。我对可选参数的了解不够,知道这些参数可能会让我得到更好的结果。

第二个给出了一个50x50x50的数组,它的前四个值[0,0:3,0]为:0.3422 0.2623 0.2810 0.3006。这是一个不同的输出数组大小,也不会复制与MATLAB代码或其他python函数相同的数值输出

我对可选参数的了解不够,知道这些参数可能会得到更好的结果。我知道对于这种类型的数组,MATLAB的默认值是三次插值,这就是为什么我在python中使用3阶。两者的默认抗锯齿设置为true。我有两个更大的数组,我有同样的问题:一个(873x873x873)数组和一个bool (873x873x873)数组。

我使用的MATLAB代码被认为是"正确答案"。对于我正在做的工作,所以我试图尽可能准确地复制结果到python。请让我知道我可以在python中尝试重现正确的数据。

sampleQDNorm是[0:100,0:100,0:100]的0到1之间的大致随机小数,[:,:,101],[:,101,:],[101,:,:]两侧填充0

获得与MATLABimresize3完全相同的结果是具有挑战性的。

一个原因是MATLAB默认启用抗锯齿滤波器,而我似乎找不到等效的Python实现。

这篇文章描述了最基本的现有Python替代方案。
scipy.ndimage。缩放支持3D调整大小。
可能skimage.transform.resize给出了更接近的结果,但没有一个与MATLAB的结果相同。


重新实现imresize3:

查看imresize3的MATLAB实现(MATLAB源代码),很明显,MATLAB实现"简单"。在每个轴上使用调整大小:

  • 沿着垂直轴调整大小(一半)
  • 沿着水平轴调整上述结果的大小(减半)。
  • 沿着深度轴调整上述结果的大小(一半)。

这是一个MATLAB代码示例,演示了实现(使用三次插值):

I1 = imread('peppers.png');
I2 = imresize(imread('autumn.tif'), [size(I1, 1), size(I1, 2)]);
I3 = imresize(imread('football.jpg'), [size(I1, 1), size(I1, 2)]);
I4 = imresize(imread('cameraman.tif'), [size(I1, 1), size(I1, 2)]);
I = cat(3, I1, I2, I3, I4);
J = imresize3(I, 0.5, 'cubic', 'Antialiasing', false);
imwrite(I1, '/Tmp/I1.png');
imwrite(I2, '/Tmp/I2.png');
imwrite(I3, '/Tmp/I3.png');
imwrite(I4, '/Tmp/I4.png');
imwrite(J(:,:,1), '/Tmp/J1.png');
imwrite(J(:,:,2), '/Tmp/J2.png');
imwrite(J(:,:,3), '/Tmp/J3.png');
imwrite(J(:,:,4), '/Tmp/J4.png');
imwrite(J(:,:,5), '/Tmp/J5.png');
K = cubicResize3(I, 0.5);
max_abs_diff = max(abs(double(J(:)) - double(K(:))));
disp(['max_abs_diff = ', num2str(max_abs_diff)])

function B = cubicResize3(A, scale)
order = [1 2 3];

B = A;
for k = 1:numel(order)
dim = order(k);       
B = cubicResizeAlongDim(B, dim, scale);
end    
end

function out = cubicResizeAlongDim(in, dim, scale)
% If dim is 3, permute the input matrix so that the third dimension
% becomes the first dimension.  This way, we can resize along the
% third dimensions as though we were resizing along the first dimension.
isThirdDimResize = (dim == 3);
if isThirdDimResize
in = permute(in, [3 2 1]);
dim = 1;
end

if dim == 1
out_rows = round(size(in, 1)*scale);
out_cols = size(in, 2);
else % dim == 2
out_rows = size(in, 1);
out_cols = round(size(in,2)*scale);
end

out = zeros(out_rows, out_cols, size(in, 3), class(in));  % Allocate array for storing the output.

for i = 1:size(in, 3)
% Resize each color plane separately
out(:, :, i) = imresize(in(:, :, i), [out_rows, out_cols], 'bicubic', 'Antialiasing', false);
end
% Permute back so that the original dimensions are restored if we were
% resizing along the third dimension.
if isThirdDimResize
out = permute(out, [3 2 1]);
end
end

结果是max_abs_diff = 0,这意味着cubicResize3imresize3给出相同的输出。

注意:
上面的实现将图像存储在Tmp文件夹中,用于测试Python实现的输入。


下面是使用OpenCV的Python实现:

import numpy as np
import cv2
#from scipy.ndimage import zoom
def cubic_resize_along_dim(inp, dim, scale):
""" Implementation is based on MATLAB source code of resizeAlongDim function """
# If dim is 3, permute the input matrix so that the third dimension
# becomes the first dimension.  This way, we can resize along the
# third dimensions as though we were resizing along the first dimension.
is_third_dim_resize = (dim == 2)
if is_third_dim_resize:
inp = np.swapaxes(inp, 2, 0).copy()  # in = permute(in, [3 2 1])
dim = 0

if dim == 0:
out_rows = int(np.round(inp.shape[0]*scale))  # out_rows = round(size(in, 1)*scale);
out_cols = inp.shape[1]  # out_cols = size(in, 2);
else: # dim == 1
out_rows = inp.shape[0]  # out_rows = size(in, 1);
out_cols = int(np.round(inp.shape[1]*scale))  # out_cols = round(size(in,2)*scale);

out = np.zeros((out_rows, out_cols, inp.shape[2]), inp.dtype)  # out = zeros(out_rows, out_cols, size(in, 3), class(in));  % Allocate array for storing the output.

for i in range(inp.shape[2]):
# Resize each color plane separately
out[:, :, i] = cv2.resize(inp[:, :, i], (out_cols, out_rows), interpolation=cv2.INTER_CUBIC)  # out(:, :, i) = imresize(inp(:, :, i), [out_rows, out_cols], 'bicubic', 'Antialiasing', false);
# Permute back so that the original dimensions are restored if we were
# resizing along the third dimension.
if is_third_dim_resize:
out = np.swapaxes(out, 2, 0) # out = permute(out, [3 2 1]);
return out

def cubic_resize3(a, scale):
b = a.copy()
for k in range(3):
b = cubic_resize_along_dim(b, k, scale)
return b

# Build 3D input image (10 channels with resolution 512x384).
i1 = cv2.cvtColor(cv2.imread('/Tmp/I1.png', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB)
i2 = cv2.cvtColor(cv2.imread('/Tmp/I2.png', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB)
i3 = cv2.cvtColor(cv2.imread('/Tmp/I3.png', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB)
i4 = cv2.imread('/Tmp/I4.png', cv2.IMREAD_UNCHANGED)
im = np.dstack((i1, i2, i3, i4))  # Stack arrays along the third axis
# Read and adjust MATLAB output (out_mat is used as reference for testing).
# out_mat is the result of J = imresize3(I, 0.5, 'cubic', 'Antialiasing', false);
j1 = cv2.imread('/Tmp/J1.png', cv2.IMREAD_UNCHANGED)
j2 = cv2.imread('/Tmp/J2.png', cv2.IMREAD_UNCHANGED)
j3 = cv2.imread('/Tmp/J3.png', cv2.IMREAD_UNCHANGED)
j4 = cv2.imread('/Tmp/J4.png', cv2.IMREAD_UNCHANGED)
j5 = cv2.imread('/Tmp/J5.png', cv2.IMREAD_UNCHANGED)
out_mat = np.dstack((j1, j2, j3, j4, j5))  # Stack arrays along the third axis
#out_py = zoom(im, 0.5, order=3, mode='reflect')
# Execute 3D resize in Python
out_py = cubic_resize3(im, 0.5)
abs_diff = np.absolute(out_mat.astype(np.int16) - out_py.astype(np.int16))
print(f'max_abs_diff = {abs_diff.max()}')

Python实现读取MATLAB存储的输入文件(并在需要时从BGR转换为RGB)。

实现将cubic_resize3的结果与imresize3的MATLAB输出进行了比较。

最大差值为12(不为零)。
显然cv2.resize和MATLABimresize给出的结果略有不同。


更新:

将:
out[:, :, i] = cv2.resize(inp[:, :, i], (out_cols, out_rows), interpolation=cv2.INTER_CUBIC)
替换为:
out[:, :, i] = transform.resize(inp[:, :, i], (out_rows, out_cols), order=3, mode='edge', anti_aliasing=False, preserve_range=True)
减少4的最大差异。

相关内容

  • 没有找到相关文章

最新更新