降尺度的双立方插值

时间:2012-08-17 09:35:42

标签: algorithm interpolation

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

我也尝试过Gernot Hoffmann的书“图像变形插值”中的双立方插值算法。

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

也许我错了什么?

我也注意到在Photoshop中有两个单独的双三次插值选项:双立方平滑器(用于高级)和双立方锐化器(用于缩小)。

那么也许有人知道用于缩减尺度的双三次插值算法?

1 个答案:

答案 0 :(得分:2)

我刚写了一个双三次插入算法... 我运作良好。 在运行之前,根据图像更改一些值;

ROW&列

#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;
}