2012-08-17 40 views
2

似乎雙三次插值僅適用於高檔。我曾嘗試這些功能: http://jsperf.com/pixel-interpolation/4http://www.reddit.com/r/javascript/comments/jxa8x/bicubic_interpolation/用於縮小比例的雙三次插值

而且我已經嘗試了兩次立方插值算法從赫爾諾特霍夫曼的書「的圖像變形插值」。

但是,使用上述方法縮小後的所有圖像看起來像是由近鄰插補的。

也許我錯了什麼?

我也注意到,在Photoshop中有兩個單獨的選項用於雙三次插值:雙三次平滑器(用於高檔)和雙三次用銳器(用於小型)。

所以也許有人知道一個三維三次插值算法的縮小?

回答

2

我剛剛寫了一個雙三次插入算法... 我工作的很好。在運行它之前,根據圖像更改一些值;

ROW & COLUMN

#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是,如果你想dublicate它,然後讓它 「2」

ZOOM_NUM的圖像的大小調整的速度= 1/ZOOM_RATE - > ZOOM_NUM等於1,超過ZOOM_RATE

名字名字和形象的延伸

INT主()功能改變

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

這裏

是源代碼:(此代碼也有雙線性interpolition,這樣你就可以比較你的結果)

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