双三次插值 matlab 实现仅适用于灰度图像
Bicubic interpolation matlab implementation works only for grayscale images
我正在尝试在 matlab 中实现用于图像缩放的双三次插值。问题是它适用于灰度图像,但是,对于彩色图像,结果又是灰度的。
请帮我找出问题所在。
谢谢。
对于双三次插值,我使用了包含梯度的矩阵。矩阵可以在 https://en.wikipedia.org/wiki/Bicubic_interpolation 找到。
这是我的代码。
input_image = im2double(imread('peppers.png'));
x_res = 700;
y_res = 700;
imshow(input_image, []);
M_inv = [
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0;
-3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0;
2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;
0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0;
0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0;
-3,0,3,0,0,0,0,0,-2,0,-1,0,0,0,0,0;
0,0,0,0,-3,0,3,0,0,0,0,0,-2,0,-1,0;
9,-9,-9,9,6,3,-6,-3,6,-6,3,-3,4,2,2,1;
-6,6,6,-6,-3,-3,3,3,-4,4,-2,2,-2,-2,-1,-1;
2,0,-2,0,0,0,0,0,1,0,1,0,0,0,0,0;
0,0,0,0,2,0,-2,0,0,0,0,0,1,0,1,0;
-6,6,6,-6,-4,-2,4,2,-3,3,-3,3,-2,-1,-2,-1;
4,-4,-4,4,2,2,-2,-2,2,-2,2,-2,1,1,1,1
];
I = input_image;
[j k c] = size(I);
%{
if c > 1
I = double(rgb2gray(I));
end
%}
x_new = x_res;
y_new = y_res;
x_scale = x_new./(j-1);
y_scale = y_new./(k-1);
temp_image = zeros(x_new,y_new);
Ix = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count2==1) || (count2==k) )
Ix(count1,count2)=0;
else
Ix(count1,count2)=(0.5).*(I(count1,count2+1)-I(count1,count2-1));
end
end
end
Iy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) )
Iy(count1,count2)=0;
else
Iy(count1,count2)=(0.5).*(I(count1+1,count2)-I(count1-1,count2));
end
end
end
Ixy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) || (count2==1) || (count2==k) )
Ixy(count1,count2)=0;
else
Ixy(count1,count2)=(0.25).*((I(count1+1,count2+1)+I(count1-1,count2-1)) - (I(count1+1,count2-1)+I(count1-1,count2+1)));
end
end
end
for count1 = 0:x_new-1
for count2 = 0:y_new-1
W = -(((count1./x_scale)-floor(count1./x_scale))-1);
H = -(((count2./y_scale)-floor(count2./y_scale))-1);
I11_index = [1+floor(count1./x_scale),1+floor(count2./y_scale)];
I21_index = [1+floor(count1./x_scale),1+ceil(count2./y_scale)];
I12_index = [1+ceil(count1./x_scale),1+floor(count2./y_scale)];
I22_index = [1+ceil(count1./x_scale),1+ceil(count2./y_scale)];
I11 = I(I11_index(1),I11_index(2));
I21 = I(I21_index(1),I21_index(2));
I12 = I(I12_index(1),I12_index(2));
I22 = I(I22_index(1),I22_index(2));
Ix11 = Ix(I11_index(1),I11_index(2));
Ix21 = Ix(I21_index(1),I21_index(2));
Ix12 = Ix(I12_index(1),I12_index(2));
Ix22 = Ix(I22_index(1),I22_index(2));
Iy11 = Iy(I11_index(1),I11_index(2));
Iy21 = Iy(I21_index(1),I21_index(2));
Iy12 = Iy(I12_index(1),I12_index(2));
Iy22 = Iy(I22_index(1),I22_index(2));
Ixy11 = Ixy(I11_index(1),I11_index(2));
Ixy21 = Ixy(I21_index(1),I21_index(2));
Ixy12 = Ixy(I12_index(1),I12_index(2));
Ixy22 = Ixy(I22_index(1),I22_index(2));
beta = [I11 I21 I12 I22 Ix11 Ix21 Ix12 Ix22 Iy11 Iy21 Iy12 Iy22 Ixy11 Ixy21 Ixy12 Ixy22];
alpha = M_inv*beta';
temp_p=0;
for count3 = 1:16
w_temp = floor((count3-1)/4);
h_temp = mod(count3-1,4);
temp_p = temp_p + alpha(count3).*((1-W)^(w_temp)).*((1-H)^(h_temp));
end
temp_image(count1+1,count2+1)=temp_p;
end
end
output_image = temp_image;
figure;
imshow(output_image);
您需要调整代码,使其分别对每个通道执行插值。简而言之,您需要制作 I
每个通道,创建 output_image
以便它具有多个通道并分别循环每个通道。
有了这些变化,我们就有了:
input_image = im2double(imread('peppers.png'));
x_res = 700;
y_res = 700;
imshow(input_image, []);
% input_image - an image on which to perform bicubic interpolation
% x_res - the new horizontal dimensions (in pixels)
% y_res - the new vertical dimensions (in pixels)
%Define the inverted weighting matrix, M^(-1), no need to recalculate it
%ever again
M_inv = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0;
-3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0;
2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;
0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0;
0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0;
-3,0,3,0,0,0,0,0,-2,0,-1,0,0,0,0,0;
0,0,0,0,-3,0,3,0,0,0,0,0,-2,0,-1,0;
9,-9,-9,9,6,3,-6,-3,6,-6,3,-3,4,2,2,1;
-6,6,6,-6,-3,-3,3,3,-4,4,-2,2,-2,-2,-1,-1;
2,0,-2,0,0,0,0,0,1,0,1,0,0,0,0,0;
0,0,0,0,2,0,-2,0,0,0,0,0,1,0,1,0;
-6,6,6,-6,-4,-2,4,2,-3,3,-3,3,-2,-1,-2,-1;
4,-4,-4,4,2,2,-2,-2,2,-2,2,-2,1,1,1,1
];
%Make a copy of the input image
%I = input_image; % Ray: Not needed here
%Determine the dimensions of the source image
%Note that we will have three values - width, height, and the number
%of color vectors, 3
[j k c] = size(input_image); % Ray: Change
%Specify the new image dimensions we want for our larger output image
x_new = x_res;
y_new = y_res;
%Determine the ratio of the old dimensions compared to the new dimensions
%Referred to as S1 and S2 in my tutorial
x_scale = x_new./(j-1);
y_scale = y_new./(k-1);
% Change by Ray - Declare new output image here with c channels
output_image = zeros(x_new, y_new, c);
% Change by Ray - Now loop through each channel
for z = 1 : c
%Declare and initialize an output image buffer
temp_image = zeros(x_new,y_new);
% New - Change by Ray. Access the right channel
I = input_image(:,:,z);
Ix = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count2==1) || (count2==k) )
Ix(count1,count2)=0;
else
Ix(count1,count2)=(0.5).*(I(count1,count2+1)-I(count1,count2-1));
end
end
end
Iy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) )
Iy(count1,count2)=0;
else
Iy(count1,count2)=(0.5).*(I(count1+1,count2)-I(count1-1,count2));
end
end
end
Ixy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) || (count2==1) || (count2==k) )
Ixy(count1,count2)=0;
else
Ixy(count1,count2)=(0.25).*((I(count1+1,count2+1)+I(count1-1,count2-1)) - (I(count1+1,count2-1)+I(count1-1,count2+1)));
end
end
end
for count1 = 0:x_new-1
for count2 = 0:y_new-1
%Calculate the normalized distance constants, h and w
W = -(((count1./x_scale)-floor(count1./x_scale))-1);
H = -(((count2./y_scale)-floor(count2./y_scale))-1);
%Determine the indexes/address of the 4 neighbouring pixels from
%the source data/image
I11_index = [1+floor(count1./x_scale),1+floor(count2./y_scale)];
I21_index = [1+floor(count1./x_scale),1+ceil(count2./y_scale)];
I12_index = [1+ceil(count1./x_scale),1+floor(count2./y_scale)];
I22_index = [1+ceil(count1./x_scale),1+ceil(count2./y_scale)];
%Calculate the four nearest function values
I11 = I(I11_index(1),I11_index(2));
I21 = I(I21_index(1),I21_index(2));
I12 = I(I12_index(1),I12_index(2));
I22 = I(I22_index(1),I22_index(2));
%Calculate the four nearest horizontal derivatives
Ix11 = Ix(I11_index(1),I11_index(2));
Ix21 = Ix(I21_index(1),I21_index(2));
Ix12 = Ix(I12_index(1),I12_index(2));
Ix22 = Ix(I22_index(1),I22_index(2));
%Calculate the four nearest vertical derivatives
Iy11 = Iy(I11_index(1),I11_index(2));
Iy21 = Iy(I21_index(1),I21_index(2));
Iy12 = Iy(I12_index(1),I12_index(2));
Iy22 = Iy(I22_index(1),I22_index(2));
%Calculate the four nearest cross derivatives
Ixy11 = Ixy(I11_index(1),I11_index(2));
Ixy21 = Ixy(I21_index(1),I21_index(2));
Ixy12 = Ixy(I12_index(1),I12_index(2));
Ixy22 = Ixy(I22_index(1),I22_index(2));
%Create our beta-vector
beta = [I11 I21 I12 I22 Ix11 Ix21 Ix12 Ix22 Iy11 Iy21 Iy12 Iy22 Ixy11 Ixy21 Ixy12 Ixy22];
alpha = M_inv*beta';
temp_p=0;
for count3 = 1:16
w_temp = floor((count3-1)/4);
h_temp = mod(count3-1,4);
temp_p = temp_p + alpha(count3).*((1-W)^(w_temp)).*((1-H)^(h_temp));
end
temp_image(count1+1,count2+1)=temp_p;
end
end
% New - Change by Ray - Assign to output channel
output_image(:,:,z) = temp_image;
end
figure;
imshow(output_image);
我正在尝试在 matlab 中实现用于图像缩放的双三次插值。问题是它适用于灰度图像,但是,对于彩色图像,结果又是灰度的。 请帮我找出问题所在。 谢谢。
对于双三次插值,我使用了包含梯度的矩阵。矩阵可以在 https://en.wikipedia.org/wiki/Bicubic_interpolation 找到。
这是我的代码。
input_image = im2double(imread('peppers.png'));
x_res = 700;
y_res = 700;
imshow(input_image, []);
M_inv = [
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0;
-3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0;
2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;
0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0;
0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0;
-3,0,3,0,0,0,0,0,-2,0,-1,0,0,0,0,0;
0,0,0,0,-3,0,3,0,0,0,0,0,-2,0,-1,0;
9,-9,-9,9,6,3,-6,-3,6,-6,3,-3,4,2,2,1;
-6,6,6,-6,-3,-3,3,3,-4,4,-2,2,-2,-2,-1,-1;
2,0,-2,0,0,0,0,0,1,0,1,0,0,0,0,0;
0,0,0,0,2,0,-2,0,0,0,0,0,1,0,1,0;
-6,6,6,-6,-4,-2,4,2,-3,3,-3,3,-2,-1,-2,-1;
4,-4,-4,4,2,2,-2,-2,2,-2,2,-2,1,1,1,1
];
I = input_image;
[j k c] = size(I);
%{
if c > 1
I = double(rgb2gray(I));
end
%}
x_new = x_res;
y_new = y_res;
x_scale = x_new./(j-1);
y_scale = y_new./(k-1);
temp_image = zeros(x_new,y_new);
Ix = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count2==1) || (count2==k) )
Ix(count1,count2)=0;
else
Ix(count1,count2)=(0.5).*(I(count1,count2+1)-I(count1,count2-1));
end
end
end
Iy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) )
Iy(count1,count2)=0;
else
Iy(count1,count2)=(0.5).*(I(count1+1,count2)-I(count1-1,count2));
end
end
end
Ixy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) || (count2==1) || (count2==k) )
Ixy(count1,count2)=0;
else
Ixy(count1,count2)=(0.25).*((I(count1+1,count2+1)+I(count1-1,count2-1)) - (I(count1+1,count2-1)+I(count1-1,count2+1)));
end
end
end
for count1 = 0:x_new-1
for count2 = 0:y_new-1
W = -(((count1./x_scale)-floor(count1./x_scale))-1);
H = -(((count2./y_scale)-floor(count2./y_scale))-1);
I11_index = [1+floor(count1./x_scale),1+floor(count2./y_scale)];
I21_index = [1+floor(count1./x_scale),1+ceil(count2./y_scale)];
I12_index = [1+ceil(count1./x_scale),1+floor(count2./y_scale)];
I22_index = [1+ceil(count1./x_scale),1+ceil(count2./y_scale)];
I11 = I(I11_index(1),I11_index(2));
I21 = I(I21_index(1),I21_index(2));
I12 = I(I12_index(1),I12_index(2));
I22 = I(I22_index(1),I22_index(2));
Ix11 = Ix(I11_index(1),I11_index(2));
Ix21 = Ix(I21_index(1),I21_index(2));
Ix12 = Ix(I12_index(1),I12_index(2));
Ix22 = Ix(I22_index(1),I22_index(2));
Iy11 = Iy(I11_index(1),I11_index(2));
Iy21 = Iy(I21_index(1),I21_index(2));
Iy12 = Iy(I12_index(1),I12_index(2));
Iy22 = Iy(I22_index(1),I22_index(2));
Ixy11 = Ixy(I11_index(1),I11_index(2));
Ixy21 = Ixy(I21_index(1),I21_index(2));
Ixy12 = Ixy(I12_index(1),I12_index(2));
Ixy22 = Ixy(I22_index(1),I22_index(2));
beta = [I11 I21 I12 I22 Ix11 Ix21 Ix12 Ix22 Iy11 Iy21 Iy12 Iy22 Ixy11 Ixy21 Ixy12 Ixy22];
alpha = M_inv*beta';
temp_p=0;
for count3 = 1:16
w_temp = floor((count3-1)/4);
h_temp = mod(count3-1,4);
temp_p = temp_p + alpha(count3).*((1-W)^(w_temp)).*((1-H)^(h_temp));
end
temp_image(count1+1,count2+1)=temp_p;
end
end
output_image = temp_image;
figure;
imshow(output_image);
您需要调整代码,使其分别对每个通道执行插值。简而言之,您需要制作 I
每个通道,创建 output_image
以便它具有多个通道并分别循环每个通道。
有了这些变化,我们就有了:
input_image = im2double(imread('peppers.png'));
x_res = 700;
y_res = 700;
imshow(input_image, []);
% input_image - an image on which to perform bicubic interpolation
% x_res - the new horizontal dimensions (in pixels)
% y_res - the new vertical dimensions (in pixels)
%Define the inverted weighting matrix, M^(-1), no need to recalculate it
%ever again
M_inv = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0;
-3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0;
2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;
0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0;
0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0;
-3,0,3,0,0,0,0,0,-2,0,-1,0,0,0,0,0;
0,0,0,0,-3,0,3,0,0,0,0,0,-2,0,-1,0;
9,-9,-9,9,6,3,-6,-3,6,-6,3,-3,4,2,2,1;
-6,6,6,-6,-3,-3,3,3,-4,4,-2,2,-2,-2,-1,-1;
2,0,-2,0,0,0,0,0,1,0,1,0,0,0,0,0;
0,0,0,0,2,0,-2,0,0,0,0,0,1,0,1,0;
-6,6,6,-6,-4,-2,4,2,-3,3,-3,3,-2,-1,-2,-1;
4,-4,-4,4,2,2,-2,-2,2,-2,2,-2,1,1,1,1
];
%Make a copy of the input image
%I = input_image; % Ray: Not needed here
%Determine the dimensions of the source image
%Note that we will have three values - width, height, and the number
%of color vectors, 3
[j k c] = size(input_image); % Ray: Change
%Specify the new image dimensions we want for our larger output image
x_new = x_res;
y_new = y_res;
%Determine the ratio of the old dimensions compared to the new dimensions
%Referred to as S1 and S2 in my tutorial
x_scale = x_new./(j-1);
y_scale = y_new./(k-1);
% Change by Ray - Declare new output image here with c channels
output_image = zeros(x_new, y_new, c);
% Change by Ray - Now loop through each channel
for z = 1 : c
%Declare and initialize an output image buffer
temp_image = zeros(x_new,y_new);
% New - Change by Ray. Access the right channel
I = input_image(:,:,z);
Ix = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count2==1) || (count2==k) )
Ix(count1,count2)=0;
else
Ix(count1,count2)=(0.5).*(I(count1,count2+1)-I(count1,count2-1));
end
end
end
Iy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) )
Iy(count1,count2)=0;
else
Iy(count1,count2)=(0.5).*(I(count1+1,count2)-I(count1-1,count2));
end
end
end
Ixy = double(zeros(j,k));
for count1 = 1:j
for count2 = 1:k
if( (count1==1) || (count1==j) || (count2==1) || (count2==k) )
Ixy(count1,count2)=0;
else
Ixy(count1,count2)=(0.25).*((I(count1+1,count2+1)+I(count1-1,count2-1)) - (I(count1+1,count2-1)+I(count1-1,count2+1)));
end
end
end
for count1 = 0:x_new-1
for count2 = 0:y_new-1
%Calculate the normalized distance constants, h and w
W = -(((count1./x_scale)-floor(count1./x_scale))-1);
H = -(((count2./y_scale)-floor(count2./y_scale))-1);
%Determine the indexes/address of the 4 neighbouring pixels from
%the source data/image
I11_index = [1+floor(count1./x_scale),1+floor(count2./y_scale)];
I21_index = [1+floor(count1./x_scale),1+ceil(count2./y_scale)];
I12_index = [1+ceil(count1./x_scale),1+floor(count2./y_scale)];
I22_index = [1+ceil(count1./x_scale),1+ceil(count2./y_scale)];
%Calculate the four nearest function values
I11 = I(I11_index(1),I11_index(2));
I21 = I(I21_index(1),I21_index(2));
I12 = I(I12_index(1),I12_index(2));
I22 = I(I22_index(1),I22_index(2));
%Calculate the four nearest horizontal derivatives
Ix11 = Ix(I11_index(1),I11_index(2));
Ix21 = Ix(I21_index(1),I21_index(2));
Ix12 = Ix(I12_index(1),I12_index(2));
Ix22 = Ix(I22_index(1),I22_index(2));
%Calculate the four nearest vertical derivatives
Iy11 = Iy(I11_index(1),I11_index(2));
Iy21 = Iy(I21_index(1),I21_index(2));
Iy12 = Iy(I12_index(1),I12_index(2));
Iy22 = Iy(I22_index(1),I22_index(2));
%Calculate the four nearest cross derivatives
Ixy11 = Ixy(I11_index(1),I11_index(2));
Ixy21 = Ixy(I21_index(1),I21_index(2));
Ixy12 = Ixy(I12_index(1),I12_index(2));
Ixy22 = Ixy(I22_index(1),I22_index(2));
%Create our beta-vector
beta = [I11 I21 I12 I22 Ix11 Ix21 Ix12 Ix22 Iy11 Iy21 Iy12 Iy22 Ixy11 Ixy21 Ixy12 Ixy22];
alpha = M_inv*beta';
temp_p=0;
for count3 = 1:16
w_temp = floor((count3-1)/4);
h_temp = mod(count3-1,4);
temp_p = temp_p + alpha(count3).*((1-W)^(w_temp)).*((1-H)^(h_temp));
end
temp_image(count1+1,count2+1)=temp_p;
end
end
% New - Change by Ray - Assign to output channel
output_image(:,:,z) = temp_image;
end
figure;
imshow(output_image);