Matlab学习笔记——双线性插值旋转图像

用普通坐标变换的方法进行旋转图像时,由于取整后的坐标不能与原来一一对应,会出现空像素即黑点,例如

I=imread('cameraman.tif');
x=pi/4;
[m,n]=size(I);
J=zeros(m,n);
for n1=1:m
    for n2=1:n
        u=floor(n1*cos(x)-n2*sin(x))+m;
        v=floor(n1*sin(x)+n2*cos(x))+n;
        J(u,v)=I(n1,n2);
    end
end
J=uint8(J);
imshow(J);

旋转效果如下图
Matlab学习笔记——双线性插值旋转图像_第1张图片

可以看到图片上明显的黑点。

为了解决这种问题,可以采取插值法将空像素点补全,常用插值法包括最邻近插值法,双线性插值法,三次内插值法。


双线性插值法实现如下:

img=imread('cameraman.tif');    
[h,w]=size(img);
img2=imrotate(img,45,'bilinear');

theta=pi/4;
rot=[cos(theta) sin(theta) 0;-sin(theta) cos(theta) 0;0 0 1]; 
pix1=[1 1 1]*rot;               %变换后图像左上点的坐标
pix2=[1 w 1]*rot;               %变换后图像右上点的坐标
pix3=[h 1 1]*rot;               %变换后图像左下点的坐标
pix4=[h w 1]*rot;               %变换后图像右下点的坐标

height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5]));     %变换后图像的高度
width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5]));      %变换后图像的宽度
imgn=zeros(height,width);

delta_y=abs(min([pix1(1) pix2(1) pix3(1) pix4(1)]));             %取得y方向的负轴超出的偏移量
delta_x=abs(min([pix1(2) pix2(2) pix3(2) pix4(2)]));             %取得x方向的负轴超出的偏移量

for i=1-delta_y:height-delta_y
    for j=1-delta_x:width-delta_x
        pix=[i j 1]/rot;                                
        %用变换后图像的点的坐标去寻找原图像点的坐标,                                         
        %否则有些变换后的图像的像素点无法完全填充
        float_Y=pix(1)-floor(pix(1)); 
        float_X=pix(2)-floor(pix(2));    

        if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w     

            pix_up_left=[floor(pix(1)) floor(pix(2))];           %四个相邻的点
            pix_up_right=[floor(pix(1)) ceil(pix(2))];
            pix_down_left=[ceil(pix(1)) floor(pix(2))];
            pix_down_right=[ceil(pix(1)) ceil(pix(2))]; 

            value_up_left=(1-float_X)*(1-float_Y);               %计算临近四个点的权重
            value_up_right=float_X*(1-float_Y);
            value_down_left=(1-float_X)*float_Y;
            value_down_right=float_X*float_Y;

            imgn(i+delta_y,j+delta_x)=value_up_left*img(pix_up_left(1),pix_up_left(2))+ ...
                                        value_up_right*img(pix_up_right(1),pix_up_right(2))+ ...
                                        value_down_left*img(pix_down_left(1),pix_down_left(2))+ ...
                                        value_down_right*img(pix_down_right(1),pix_down_right(2));
        end       

    end
end
subplot(1,2,1);imshow(img2);title('imrotate双线性插值旋转');
subplot(1,2,2);imshow(uint8(imgn));title('手动双线性插值旋转');

运行结果
Matlab学习笔记——双线性插值旋转图像_第2张图片
可以看到右侧双线性插值旋转后的图片没有上图中的黑点出现,说明空像素点得到了对应的填充,效果较好。

你可能感兴趣的:(Matlab学习,matlab,图像处理)