Matlab:使用自定义插值内核 Mitchell-Netravali 调整大小

Matlab: resize with custom interpolation kernel Mitchell-Netravali

我看到有人对用于调整大小的自定义插值内核感兴趣 (MATLAB imresize with a custom interpolation kernel)。是否有人实现了 ImageMagick 中默认使用的参数化 Mitchell-Netravali 内核 [1] 并愿意共享 Matlab 代码?非常感谢!

[1] http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch24.html

// Mitchell Netravali Reconstruction Filter
// B = 0    C = 0   - Hermite B-Spline interpolator 
// B = 1,   C = 0   - cubic B-spline
// B = 0,   C = 1/2 - Catmull-Rom spline
// B = 1/3, C = 1/3 - recommended

float MitchellNetravali(float x, float B, float C)
{
 float ax = fabs(x);
 if (ax < 1) {
 return ((12 - 9 * B - 6 * C) * ax * ax * ax +
        (-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
} else if ((ax >= 1) && (ax < 2)) {
  return ((-B - 6 * C) * ax * ax * ax +
          (6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
          ax + (8 * B + 24 * C)) / 6;
} else {
  return 0;
 }
}

我得到了以下针对 imresize 调用的 Mitchel 内核的建议,其中参数 B 和 C 以及使用 for 循环(和预分配)的内核半径:

img_resize = imresize(img, [h w], {@(x)Mitchell(x,B,C),radius}); 

function [outputs] = Mitchell(x,B,C)
outputs= zeros(size(x,1),size(x,2)); 
    for i = 1 : size(x,1)
        for j = 1 : size(x,2)
            ax = abs(x(i,j));
            if ax < 1
                outputs(i,j) = ((12-9*B-6*C) * ax^3 + (-18+12*B+6*C) * ax^2 + (6-2*B))/6;
            elseif (ax >= 1) && (ax < 2)
                outputs(i,j) = ((-B-6*C) * ax^3 + (6*B+30*C) * ax^2 + (-12*B-48*C) * ax + (8*B + 24*C))/6;
            else 
                outputs(i,j) = 0;
            end
        end
    end
end

这里我得到了另一种矢量化方法;根据我的放大测试(1000x1000 -> 3000x3000),即使米切尔半径很大= 6,这也比标准双三次更快:

function [outputs] = Mitchell_vect(x,M_B,M_C)
   outputs= zeros(size(x,1),size(x,2)); 
   ax = abs(x);
   temp = ((12-9*M_B-6*M_C) .* ax.^3 + (-18+12*M_B+6*M_C) .* ax.^2 + (6-2*M_B))./6;
   temp2 = ((-M_B-6*M_C) .* ax.^3 + (6*M_B+30*M_C) .* ax.^2 + (-12*M_B-48*M_C) .* ax + (8*M_B + 24*M_C))./6;
   index = find(ax<1);
   outputs(index)=temp(index);
   index = find(ax>=1 & ax<2);
   outputs(index)=temp2(index);
end