【问题标题】:Bicubic interpolation for downscale用于缩小的双三次插值
【发布时间】:2012-10-31 09:47:47
【问题描述】:

似乎双三次插值仅适用于高档。我试过这些功能: http://jsperf.com/pixel-interpolation/4http://www.reddit.com/r/javascript/comments/jxa8x/bicubic_interpolation/

我还尝试了 Gernot Hoffmann 的“图像扭曲插值”一书中的双三次插值算法。

但是使用上述方法缩小后的所有图像看起来都是近邻插值的。

也许我做错了什么?

我还注意到,在 Photoshop 中,双三次插值有两个单独的选项:Bicubic Smoother(用于放大)和 Bicubic Sharper(用于缩小)。

所以也许有人知道用于缩小比例的双三次插值算法?

【问题讨论】:

    标签: algorithm interpolation


    【解决方案1】:

    我刚刚写了一个双三次插值算法... 我工作得很好。 在运行它之前,根据您的图像更改一些值;

    行和列

    #define ROW 218     //change 218 to your image's horizantol pixels 
    #define COLUMN 329` //change 329 to your image's vertical pixels
    

    ZOOM_RATE & ZOOM_NUM

    ZOOM_RATE 是您的图像调整大小的速率,如果您想复制它然后将其设为“2”

    ZOOM_NUM=1/ZOOM_RATE -> ZOOM_NUM 等于 ZOOM_RATE 的 1

    图片的名称和扩展名

    int main()函数中改变

    readPpm("irfan.ppm");    //change irfan to your image's name
    

    这里是源代码:(这个代码也有双线性插值,所以你可以比较你的结果)

    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <fstream>
    #include <string.h>
    #include <string>
    #include <sstream>
    #include <string.h>
    #include <vector>
    #include <math.h>
    
    using namespace std;
    #define ROW 218
    #define COLUMN 329
    #define ZOOM_RATE 2
    #define ZOOM_NUM 1/2
    
    struct POINT {   // Declare POINT structure
       int x;   // Define members x and y
       int y;
       int renk;
    } ;    // Variable spot has
                            // values x = 20, y = 40
    
    typedef struct POINT coordinate;     // Variable there has POINT type
    
    int int_arr[ROW][COLUMN*3];
    int int_arr_simple[ROW][COLUMN];
    int zoom_photo[(int)(ROW*ZOOM_RATE)][(int)(COLUMN*ZOOM_RATE)];
    int zoom_photo_bicubic[(int)(ROW*ZOOM_RATE)][(int)(COLUMN*ZOOM_RATE)];
    string filetype;
    string comment;
    string size;
    string colorrange;
    
    int line_find(int ,int,int,int,float);
    void save2Ppm(string filename,int pixel[ROW][COLUMN*3],int size);
    void save2Pgm(string filename,int pixel[ROW][COLUMN],int size);
    void save2Pgm_zoom(string filename,int pixel[ROW*ZOOM_RATE][COLUMN*ZOOM_RATE],int size);
    void readPpm(string);
    void zooming();
    void zooming_bilinear();
    void zooming_bicubic();
    int bicubic_function(float x_cor,float y_cor);
    
    void save2Pgm_zoom(string filename,int pixel[ROW*ZOOM_RATE][COLUMN*ZOOM_RATE],int size){
        ofstream Picture;
        Picture.open(filename);
        Picture<<"P2\n#"<<filename<<"\n"<<(int)(COLUMN*ZOOM_RATE)<<" "<<(int)(ROW*ZOOM_RATE)<<"\n"<<size<<"\n";    
    
        for(int i=0 ; i<ROW*ZOOM_RATE ; i++)
        {
            for(int j=0; j<COLUMN*ZOOM_RATE; j++){
                Picture<<pixel[i][j]<<" ";
            }
        }
        Picture.close();
    }
    void zooming(){
        for(int i=0;i<ROW*ZOOM_RATE;i++){
            for(int j=0;j<COLUMN*ZOOM_RATE;j++){
                zoom_photo[i][j]=int_arr_simple[i*ZOOM_NUM][j*ZOOM_NUM];
            }
        }   
    }
    void save2Pgm(string filename,int pixel[ROW][COLUMN],int size){
        ofstream Picture;
        Picture.open(filename);
        Picture<<"P2\n#"<<filename<<"\n"<<COLUMN<<" "<<ROW<<"\n"<<size<<"\n";    
    
        for(int i=0 ; i<ROW ; i++)
        {
            for(int j=0; j<COLUMN; j++){
                Picture<<pixel[i][j]<<" ";
            }
        }
        Picture.close();
    }
    void save2Ppm(string filename,int pixel[ROW][COLUMN*3],int size){
        ofstream Picture;
        Picture.open(filename);
        Picture<<"P3\n#"<<filename<<"\n"<<COLUMN<<" "<<ROW<<"\n"<<size<<"\n";    
    
        for(int i=0 ; i<ROW ; i++)
        {
            for(int j=0; j<COLUMN*3; j++){
                Picture<<pixel[i][j]<<" ";
            }
        }
        Picture.close();
    }
    void readPpm(string filename){
        ifstream Picture(filename);
        //Picture.open(filename);
        char take[10000];
    
        if(!Picture)
            printf("FILE NOT OPEN!!!!!!\n");
        else
        {
            Picture.getline( take, 10000 ); 
            for(int i = 0; take[i] != 0; i++)
                filetype += take[i];
            Picture.getline( take, 10000 );
            for(int i = 0; take[i] != 0; i++)
                comment += take[i];
            Picture.getline( take, 10000 );
            for(int i = 0; take[i] != 0; i++)
                size += take[i];
            Picture.getline( take, 10000 ); 
            for(int i = 0; take[i] != 0; i++)
                colorrange += take[i];
    
            Picture.getline( take, 10000 ,' ');
            int_arr[0][0]=atoi(take);
            for(int i=1,j=0,t=0;i<ROW*COLUMN*3;i++){    
                Picture.getline( take, 10000 ,' ');
                t=i%(COLUMN*3);
                if(i%(COLUMN*3)==0)
                    j++;
                int_arr[j][t]=atoi(take);
                int_arr_simple[j][t/3]=int_arr[j][t];
            }
            Picture.close();
        }
    }
    void zooming_bilinear(){
        double x,y;
        double result_x,result_y,result;
        double x_1,x1;
        double y_1,y1;
        for(int i=0;i<ROW*ZOOM_RATE;i++){
            for(int j=0;j<COLUMN*ZOOM_RATE;j++){
                y=(double)ZOOM_NUM*i;
                x=(double)ZOOM_NUM*j;
    
                x_1 = (int)x;       y_1 = (int)y;
                x1  = (int)(x+1);    y1 = (int)(y+1);
    
                result_x=(double)(x1-x)*int_arr_simple[(int)y_1][(int)x_1]/(double)(x1-x_1) + (double)(x-x_1)*int_arr_simple[(int)y_1][(int)x1]/(double)(x1-x_1);
                result_y=(double)(x1-x)*int_arr_simple[(int)y1][(int)x_1] /(double)(x1-x_1) + (double)(x-x_1)*int_arr_simple[(int)y1][(int)x_1]/(double)(x1-x_1);
                result=(double)(y1-y)*result_x/(double)(y1-y_1)                   + (double)(y-y_1)*result_y /(double)(y1-y_1   );
    
                zoom_photo[i][j]=result;
            }
        }   
    
    }
    void zooming_bicubic(){
        double x,y;
        double result_x,result_y,result;
        double x_1,x1;
        double y_1,y1;
    
        //zoom 16 pixel arasında olduğu için verileri atmaya 2,2 den başlıyor   ve 2 birim önce bitiyor...
        for(int i=1;i<ROW*ZOOM_RATE-1;i++){
            for(int j=1;j<COLUMN*ZOOM_RATE-1;j++){
                zoom_photo_bicubic[i][j]=bicubic_function((float)ZOOM_NUM*j,(float)ZOOM_NUM*i);
            }
        }   
    }
    int bicubic_function(float x_cor,float y_cor){//bicubic yöntemle renk döndürmek için kullanılan fonksiyon
        coordinate nokta[4][4];
        int result;//en sonunda rengi döndüren variable
        nokta[0][0].x=(int)y_cor-1;             nokta[0][0].y=(int)x_cor-1;
        nokta[0][1].x=(int)y_cor-1;             nokta[0][1].y=(int)x_cor;
        nokta[0][2].x=(int)y_cor-1;             nokta[0][2].y=(int)x_cor+1;
        nokta[0][3].x=(int)y_cor-1;             nokta[0][3].y=(int)x_cor+2;
        nokta[1][0].x=(int)y_cor;               nokta[1][0].y=(int)x_cor-1;
        nokta[1][1].x=(int)y_cor;               nokta[1][1].y=(int)x_cor;
        nokta[1][2].x=(int)y_cor;               nokta[1][2].y=(int)x_cor+1;
        nokta[1][3].x=(int)y_cor;               nokta[1][3].y=(int)x_cor+2;
        nokta[2][0].x=(int)y_cor+1;             nokta[2][0].y=(int)x_cor-1;
        nokta[2][1].x=(int)y_cor+1;             nokta[2][1].y=(int)x_cor;
        nokta[2][2].x=(int)y_cor+1;             nokta[2][2].y=(int)x_cor+1;
        nokta[2][3].x=(int)y_cor+1;             nokta[2][3].y=(int)x_cor+2;
        nokta[3][0].x=(int)y_cor+2;             nokta[3][0].y=(int)x_cor-1;
        nokta[3][1].x=(int)y_cor+2;             nokta[3][1].y=(int)x_cor;
        nokta[3][2].x=(int)y_cor+2;             nokta[3][2].y=(int)x_cor+1;
        nokta[3][3].x=(int)y_cor+2;             nokta[3][3].y=(int)x_cor+2;
    
        float xline_1,xline_2,xline_3,xline_4;
    
        int P00,P01,P02,P03;
        P00=int_arr_simple[nokta[0][0].x][nokta[0][0].y-1];
        P01=int_arr_simple[nokta[0][1].x][nokta[0][1].y-1];
        P02=int_arr_simple[nokta[0][2].x][nokta[0][2].y-1];
        P03=int_arr_simple[nokta[0][3].x][nokta[0][3].y-1];
    
    
    
        int P10,P11,P12,P13;
        P10=int_arr_simple[nokta[1][0].x][nokta[1][0].y-1];
        P11=int_arr_simple[nokta[1][1].x][nokta[1][1].y-1];
        P12=int_arr_simple[nokta[1][2].x][nokta[1][2].y-1];
        P13=int_arr_simple[nokta[1][3].x][nokta[1][3].y-1];
    
    
        int P20,P21,P22,P23;
        P20=int_arr_simple[nokta[2][0].x][nokta[2][0].y-1];
        P21=int_arr_simple[nokta[2][1].x][nokta[2][1].y-1];
        P22=int_arr_simple[nokta[2][2].x][nokta[2][2].y-1];
        P23=int_arr_simple[nokta[2][3].x][nokta[2][3].y-1];
    
    
        int P30,P31,P32,P33;
        P30=int_arr_simple[nokta[3][0].x][nokta[3][0].y-1];
        P31=int_arr_simple[nokta[3][1].x][nokta[3][1].y-1];
        P32=int_arr_simple[nokta[3][2].x][nokta[3][2].y-1];
        P33=int_arr_simple[nokta[3][3].x][nokta[3][3].y-1];
    
    
                        xline_1=line_find(P00,P01,P02,P03, x_cor-(int)x_cor);
                        xline_2=line_find(P10,P11,P12,P13, x_cor-(int)x_cor);
                        xline_3=line_find(P20,P21,P22,P23, x_cor-(int)x_cor);
                        xline_4=line_find(P30,P31,P32,P33, x_cor-(int)x_cor);
          result=line_find(xline_1,xline_2,xline_3,xline_4,y_cor-(int)y_cor);
    
        return result;
    
    }
    int line_find(int P0,int P1,int P2,int P3, float x) {   // bir denklemin "rengini" çevirmek için kullanılır....
        float A,B,C,D,result;
        A=(float)(-(float)1/2)*(float)P0 + ((float)3/2)*(float)P1       + (-(float)3/2)*(float)P2 + ((float)1/2)*(float)P3   ;
        B=(float)P0     + (-(float)5/2)*(float)P1       + (2)*(float)P2 + (-(float)1/2)*(float)P3           ;
        C=(-(float)1/2)*(float)P0   + ((float)1/2)*(float)P2                                        ;
        D=(float)P1                                                     ;
        result=A*x*x*x + B*x*x + C*x + D ;
        return result;
    }
    int main (){
        readPpm("irfan.ppm");
        save2Ppm("ppm",int_arr,255);
        save2Pgm("pgm",int_arr_simple,255);
        zooming_bilinear();
        save2Pgm_zoom("zoom_bilinear",zoom_photo,255);
        zooming_bicubic();
        save2Pgm_zoom("zoom_bicubic",zoom_photo_bicubic,255);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-23
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-27
      相关资源
      最近更新 更多