[数字图像处理]最近邻插值和双线性插值(nearest neighbor interpolation and bilinear interpolation)实验报告
Introduction:
Through this LAB, I have known the principle and formula of nearest neighbor interpolation and bilinear interpolation, and Use nearest neighbor interpolation and bilinear interpolation to interpolate a grey scale image. At the same time, I find some aspects that can be optimized in these two methods.
Lab results & Analysis:
- Use nearest neighbor interpolation to interpolate a grey scale image:
- Introduction of the nearest neighbor interpolation algorithm:
Figure 1 the area of pixels
Let i + u, j + v (i, j is a positive integer, u, v is a decimal greater than zero and less than 1) be the pixel coordinate we want to get, then the greyscale we want to know is f (i + u, j + v).
If (i + u, j + v) falls in area A, that is u<0.5 and v<0.5, the greyscale of the upper-left pixel will be assigned to the pixel we want to get. Similarly, if it falls in area B, the greyscale of the upper-right pixel will be assigned; if it falls in area C, the greyscale of the lower-left pixel will be assigned; if it falls in area D, the greyscale of the lower-right pixel will be assigned.
This algorithm is simple and easy to understand and program, so that I will not write the pseudo code for this algorithm. I will give detailed comments in the program.
- Matlab codes:
clear;
close all;
clc;
img = imread('rice.tif');
[ input_img,new_img ] = Nearest_11711118(img,[.8,.8]);
show(img,new_img);
function show(img,new_img)%print the figure
[height,width] = size(img);
figure;imshow(img);
axis on
title(['Input Figure with Size(',num2str(height),'*',num2str(width),'):']);
[new_height,new_width,] =size(new_img);
figure;imshow(new_img);
axis on
title(['Output Figure with Size( ',num2str(new_height),'*',num2str(new_width),'):']);
end
function[ input_img,new_img ]= Nearest_11711118(input_img, dim)
input_img=double(input_img);
swh=size(input_img); %Get the width and height of the original image
inputWidth=swh(:,2); %Get the width of the original image
inputHigh=swh(:,1); %Get the height of the original image
r=dim(:,1);
c=dim(:,2);
outputHigh=ceil(inputHigh * c);
outputWidth=ceil(inputWidth * r);
new_img=zeros(outputHigh,outputWidth);
orignalx = [1:outputHigh];
orignaly = [1:outputWidth];
for i=1:outputHigh
orignalx(i)=round(i/r);
end
for j=1:outputWidth
orignaly(j)=round(j/c);
end
for i=1:outputHigh
for j=1:outputWidth
if(orignalx(i) < 1) %If the coordinates cross the border, make adjustments
orignalx(i) = 1;
end
if(orignalx(i) > inputHigh)
orignalx(i) = swh;
end
if(orignaly(j) < 1)
orignaly(j) = 1;
end
if(orignaly(j) > inputWidth)
orignaly(j) = inputWidth;
end
new_img(i,j)=input_img(orignalx(i),orignaly(j)); %The Grayscale of the position of the scaled image coordinate at the original image is assigned to the scaled image
end
end
new_img=uint8(new_img);
end
- The output figure of the program:
Figure 2 shrinked figure
Figure 3 enlarged figure
- Analysis and conclusions:
The Advantages and disadvantages of nearest neighbor interpolation:
- Advantages: The algorithm is simple, the program computation is small, the speed is fast.
- Disadvantages: Nearest neighbor interpolation will cause the discontinuity of the greyscale of the image generated by interpolation, and there may be obvious zigzag where the greyscale changes. So that using nearest neighbor interpolation to enlarge image is very jagged and shrink image is very distorted.
Then we take a closer look at our pictures to verify the Analysis:
Figure 4 closer look of shrink figure
Figure 5 : the closer look of the enlarged figure
We can see it clearly the details in enlarge image is very jagged and details in shrink image is very distorted. The root of the result is bad is the nearest neighbor interpolation caused serious image distortion, for example, when the target figure's push to get the coordinates of the source map is the coordinates of a floating number, the rounding method was adopted, directly using the floating-point number and the nearest pixel value, this method is not scientific, when pushed to coordinate values of 0.75, should not take 1 is simple, the number is 0.25 smaller than 1. It is 0.75 larger than 0.
The target pixel value should be calculated according to the real points around the virtual point in the source graph, so as to achieve a better scaling effect.
- Optimization of the algorithm:
I think of two optimization aspects:
- The first one is because the nearest neighbor interpolation algorithm to find the coordinates in the source image is fixed, we can put each target each x and each y corresponding value through a loop first to find out, and then enter the double loop. The speed of the program had been improved clearly.
The optimized codes are(in order to save the space, I only show the function part):
function put_img = Nearest_11711118(input_img, dim)
ima=imread(input_img);
imshow(ima);
title('In put Figure');
ima=double(ima);
swh=size(ima); %Get the width and height of the original image
inputWidth=swh(:,2); %Get the width of the original image
inputHigh=swh(:,1); %Get the height of the original image
r=dim(:,1);
c=dim(:,2);
outputHigh=ceil(inputHigh * c);
outputWidth=ceil(inputWidth * r);
resIma=zeros(outputHigh,outputWidth);
orignalx = [1:outputHigh];
orignaly = [1:outputWidth];
for i=1:outputHigh
orignalx(i)=round(i/r);
end
for j=1:outputWidth
orignaly(j)=round(j/c);
end
for i=1:outputHigh
for j=1:outputWidth
if(orignalx(i) < 1) %If the coordinates cross the border, make adjustments
orignalx(i) = 1;
end
if(orignalx(i) > inputHigh)
orignalx(i) = swh;
end
if(orignaly(j) < 1)
orignaly(j) = 1;
end
if(orignaly(j) > inputWidth)
orignaly(j) = inputWidth;
end
resIma(i,j)=ima(orignalx(i),orignaly(j)); %The Grayscale of the position of the scaled image coordinate at the original image is assigned to the scaled image
end
end
resIma=uint8(resIma);
figure;
imshow(resIma);
title('The Output Figure');
end
- The second is that using pointers is more efficient. This idea is come from the experience of C++, I think when I write this kind of data in C++, I will use pointer. But in matlab, I can not use pointer so far. I will do this idea in the feature.
- Use bilinear interpolation to interpolate a grey scale image:
- Introduction of the bilinear interpolation algorithm:
Figure 6 example of bilinear interpolation
The key idea is to perform linear interpolation first in one direction, and then again in the other direction.
If we want to know the value of the unknown function f at the point P = (x, y), let's say we know the value of the function f at the points Q11 = (x1, y1), Q12 = (x1, y2), Q21 = (x2, y1), and Q22 = (x2, y2).
First, perform linear interpolation in the x direction, and get:
And then we do linear interpolation in the y direction, and we can get:
So that, the value of
Pseudo code of the algorithm:
Input: original image :img, scaling factor:dim
Output: output image,
- Get the size of Img, denoted as height * width , and then generate the full 0 matrix new_img of (dim.height) * (dim. width) l;
- Extend the Img boundary the size is (height+2) * (width+2);
- For a pixel position (zi,zj) in the new scaled image new_img, map back to (zi/ dim.height,zj/ dim. width) and get (x,y) in the original image Img, since (x,y) is not set as an integer, so round down to get (i,j), where x = i + u,y = j + v.
- Calculate the value of f(zi,zj) by bilinear interpolation according to the following formula, that is,
f (x, y) = (1 - u) * (1 - v) * f (I, j) + (1 - u) * v * f (I, j + 1) + u * (1 - v) * f (I + 1, j) + u * v * f (I + 1, j + 1);.
- Repeat 3-4 until the matrix new_img is replaced.
- Matlab codes:
clear;
close all;
clc;
img = imread('rice.tif');
[ori,img_new] = Bilinear_11711118(img,[0.8,0.8]);
show(ori,img_new);
function show(original,new_img)
[height,width] = size(original);
figure;imshow(original);
axis on
title(['Input Figure with Size(',num2str(height),'*',num2str(width),'):']);
[new_height,new_width,] =size(new_img);
figure;imshow(new_img);
axis on
title(['Output Figure with Size( ',num2str(new_height),'*',num2str(new_width),'):']);
end
function [ original,new_img ] = Bilinear_11711118( original,dim )
[height,width] = size(original);
new_height = round(height*dim(:,1)); % Calculate the height of the scaled image
new_width = round(width*dim(:,2)); % %calculates the width of the scaled image
new_img = zeros(new_height,new_width);
%%Extend the size of matrix
img_scale = zeros(height+2,width+2);
img_scale(2:height+1,2:width+1,:) = original;
%%assigns values to the extended edges
img_scale(1,2:width+1,:) = original(1,:,:);
img_scale(height+2,2:width+1,:) = original(height,:,:);
img_scale(2:height+1,1,:) = original(:,1,:);
img_scale(2:height+1,width+2,:) = original(:,width,:);
%%assign values to the extended four vertices
img_scale(1,1,:) = original(1,1,:);
img_scale(1,width+2,:) = original(1,width,:);
img_scale(height+2,1,:) = original(height,1,:);
img_scale(height+2,width+2,:) = original(height,width,:);
for zj = 1:new_width
for zi = 1:new_height
% (zi,zj) represents the coordinates in the new diagram
% ( ii,jj) represents the coordinates in the original diagram
ii = (zi-1)/dim(:,1); jj = (zj-1)/dim(:,2);
i = floor(ii); j = floor(jj);
u = ii - i; v = jj - j;
i = i + 1; j = j + 1;
new_img(zi,zj,:) = (1-u)*(1-v)*img_scale(i,j,:) + u*(1-v)*img_scale(i,j+1,:)...
+ (1-u)*v*img_scale(i+1,j,:) + u*v*img_scale(i+1,j+1,:);
end
end
new_img = uint8(new_img);
end
- The output figure of the program:
Figure 7 shrinked figure
Figure 8 enlarged figure
- Analysis and conclusions:
The image quality of the bilinear interpolation algorithm is high. The greyscale is continuous. However, this algorithm has the property of low-pass filter, which damages the high-frequency components, so the image contour may be blurred to some extent.
Then we take a closer look at our pictures to verify the Analysis:
and we can see that the figure contour is blurred to some extent.
Figure 9 closer look of enlarged figure
- Optimization of algorithm:
I think of two optimization aspects:
- Alignment of the geometric centers of the origin figure and target figure:
- Method: when calculating the floating point coordinates of the source image:
SrcX = dstX * (srcWidth/dstWidth),
SrcY = dstY * (srcHeight/dstHeight)
Center alignment:
SrcX = (dstX + 0.5) * (srcWidth/dstWidth) to 0.5
SrcY = (dstY + 0.5) * (srcHeight/dstHeight) to 0.5
- proof:
SrcX =dstX* (srcWidth/dstWidth)+0.5*(srcWidth/dstWidth-1)
This is equivalent to adding 0.5*(srcWidth/dstWidth-1) to the original floating point coordinates. The symbol can be positive or negative, depending on the ratio of srcWidth/dstWidth. Let's take an example: suppose the source image is 3*3, the center point coordinate (1,1) and the target image is 9*9, and the center point coordinate (4,4). When we do the interpolation, we want to use the pixel information of the source image as evenly as possible. The most intuitive is that (4,4) maps to (1,1). That is srcX=4*3/9=1.3333!=1, the pixels we used in the interpolation are concentrated in the lower right of the image, rather than evenly distributed throughout the image. Now consider center alignment, srcX=(4+0.5)*3/9-0.5=1, which just meets our requirements.