zoukankan      html  css  js  c++  java
  • matlab练习程序(图像旋转,双线性插值)

      有好多算法早就想实现了,可是总有各种原因没有实现,这个双线性插值旋转图像就是其中之一。

      之前写过最邻近插值旋转图像,传送门。结合着看效果会很好。

    clear all;
    close all;
    clc;
    
    jiaodu=45;                       %要旋转的角度,旋转方向为顺时针
    img=imread('lena.jpg');       %这里v为原图像的高度,u为原图像的宽度
    imshow(img);                    %这里y为变换后图像的高度,x为变换后图像的宽度
    [h w]=size(img);
    
    theta=jiaodu/180*pi;
    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
    
    figure,imshow(uint8(imgn))

    原图

    最邻近插值旋转

    双线性插值旋转

    后记:

    上面的无法通过极限情况,如果旋转为90度或180度,边界会有黑像素。修改如下:

    main.m

    clear all;
    close all;
    clc;
    
    jiaodu=90;                       %要旋转的角度,旋转方向为顺时针
    img=imread('lena.jpg');       %这里v为原图像的高度,u为原图像的宽度
    imshow(img);                    %这里y为变换后图像的高度,x为变换后图像的宽度
    [h w]=size(img);
    
    theta=jiaodu/180*pi;
    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方向的负轴超出的偏移量
    
    imgm=img_extend(img,1);     %扩展边界得到的图像
    
    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+1 && pix(2) <= w+1     
                
                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*imgm(pix_up_left(1)+2,pix_up_left(2)+2)+ ...
                                            value_up_right*imgm(pix_up_right(1)+2,pix_up_right(2)+2)+ ...
                                            value_down_left*imgm(pix_down_left(1)+2,pix_down_left(2)+2)+ ...
                                            value_down_right*imgm(pix_down_right(1)+2,pix_down_right(2)+2);
            end       
            
        end
    end
    
    figure,imshow(uint8(imgn))

    img_extend.m

    function imgm=img_extend(img,r)
        [m n]=size(img);
    
        imgm=zeros(m+2*r+1,n+2*r+1);
    
        imgm(r+1:m+r,r+1:n+r)=img;
        imgm(1:r,r+1:n+r)=img(1:r,1:n); 
        imgm(1:m+r,n+r+1:n+2*r+1)=imgm(1:m+r,n:n+r);
        imgm(m+r+1:m+2*r+1,r+1:n+2*r+1)=imgm(m:m+r,r+1:n+2*r+1);
        imgm(1:m+2*r+1,1:r)=imgm(1:m+2*r+1,r+1:2*r);
    
    end
  • 相关阅读:
    ViewPager留出边 显示左右两边的视图
    Retrofit 2.0 上传文件
    android一个app打开另一个app的指定页面
    Java多线程消费者、生产者的基本思路
    Android 8.0+ 更新安装apk失败的问题
    Android 8.0+ 通知不显示的适配
    android 7.0+ FileProvider 访问隐私文件 相册、相机、安装应用的适配
    android 6.0+ 动态权限 拒绝不再询问后跳转设置应用详情页面
    ViewPager中Fragment的重复创建、复用问题
    Android源码学习(2) Handler之Looper
  • 原文地址:https://www.cnblogs.com/tiandsp/p/2800373.html
Copyright © 2011-2022 走看看