似乎双三次插值仅适用于高档。我试过这些功能: http://jsperf.com/pixel-interpolation/4和 http://www.reddit.com/r/javascript/comments/jxa8x/bicubic_interpolation/
我也尝试过Gernot Hoffmann的书“图像变形插值”中的双立方插值算法。
但是使用上述方法缩小后的所有图像看起来都是由近邻插值的。
也许我错了什么?
我也注意到在Photoshop中有两个单独的双三次插值选项:双立方平滑器(用于高级)和双立方锐化器(用于缩小)。
那么也许有人知道用于缩减尺度的双三次插值算法?
答案 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;
}