双线性插值的图像缩放算法的研究与实现

来源:互联网 发布:搜索引擎优化建议 编辑:程序博客网 时间:2024/05/21 11:17

 最简单的插值算法是最邻近插值,也称为零阶插值。它输出的像素灰度值就等于距离它映射到的位置最近的输入像素的灰度值,最邻近插值算法简单,在许多情况下都能得到令人满意的结果,但是当图像中包含像素之间灰度级有变化的细微结构时,最邻近算法会在图像中产生人为加工的痕迹。双线性插值算法计算量比零阶插值大,但缩放后图像质量高,不会出现像素值不连续的情况,这样就可以获得一个令人满意的结果。

   双线性插值是利用了需要处理的原始图像像素点周围的四个像素点的相关性,通过双线性算法计算得出的。对于一个目的坐标,通过向后映射法得到其在原始图像的对应的浮点坐标(i+u,j+v),其中i,j均为非负整数,u,v为[0,1]区间的浮点数,则这个像素的值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:f(i+u,j+v) =(1-u)×(1-v) ×f(i,j)+(1-u) ×v×f(i,j+1)+u×(1-v) ×f(i+1,j)+u×v×f(i+1,j+1),其中f(i,j)表示源图像(i,j)处的像素值,以此类推,这就是双线性内插值法。

如图1所示,已知(0,0)、(0,1)、(1,0)、(1,1)四点的灰度,可以由相邻像素的灰度值f(0,0)和f(1,0) 在X方向上线性插值求出(x,0)的灰度f(x,0),由另外两个相邻像素f(0,1)和f(1,1)在X方向上线性插值可求出(x,1)的灰度f(x,1),最后由f(x,0)、f(x,1)在Y方向上进行线性插值就可以得到(x,y)的灰度f(x,y)。


算法步骤:

假设原始图像大小为size=m×n,其中m与n分别是原始图像的行数与列<数。若图像的缩放因子是t(t>0),则目标图像的大小size=t×m×t×n。对于目标图像的某个像素点P(x,y)通过P*1/t可得到对应的原始图像坐标P’( x1,y1),其中x1=x/t,y1=y/t,由于x1,y1都不是整数所以并不存在这样的点,这样可以找出与它相邻的四个点的灰度f1、f2、f3、f4,使用双线性插值算法就可以得到这个像素点P’(x1,y1)的灰度,也就是像素点P(x,y)的灰度。

一个完整的双线性插值算法可描述如下:

(1)       通过原始图像和比例因子得到新图像的大小,并创建新图像。

(2)       由新图像的某个像素(x,y)映射到原始图像(x’,y’)处。

(3)       对x’,y’取整得到(xx,yy)并得到(xx,yy)、(xx+1,yy)、(xx,yy+1)和(xx+1,yy+1)的值。

(4)       利用双线性插值得到像素点(x,y)的值并写回新图像。

(5)       重复步骤(2)直到新图像的所有像素写完。

核心代码:

void ImageResize(const IplImage* src, IplImage* dst){


int src_width =  src->width;
int src_height = src->height;
int dst_width =  dst->width;
int dsr_height = dst->height;
int src_step = src->widthStep;
int dst_step = dst->widthStep;


unsigned char* src_data =(unsigned char*) src->imageData;
unsigned char* dst_data =(unsigned char*) dst->imageData;


float horScaleRatio = src_width / (float)(dst_width);
float verScaleRatio = src_height / (float)(dsr_height);
int int_srcx1,int_srcx2,int_srcy1,int_srcy2;
float weight_x1,weight_x2,weight_y1,weight_y2;


for(int y=0; y < dsr_height; y++){
float srcy1 = y * verScaleRatio;
int_srcy1 = (int)srcy1;
if(int_srcy1 == src_height){
int_srcy2 = int_srcy1;
}
else{
int_srcy2 = int_srcy1 + 1;
}
weight_y1 = srcy1 - int_srcy1;
weight_y2 = 1.0f - weight_y1;




for(int x=0; x< dst_width; x++){
float srcx1 = x * horScaleRatio;
int_srcx1 = (int)srcx1;
if(int_srcx1 == src_width){
int_srcx2 = int_srcx1;
}
else{
int_srcx2 = int_srcx1 + 1;
}
weight_x1 = srcx1 - int_srcx1;
weight_x2 = 1.0f - weight_x1;
double k = 0;
k = (weight_x1 * weight_y1) * src_data[int_srcy2*src_step + int_srcx2] + (weight_x2 * weight_y1) * src_data[int_srcy2*src_step + int_srcx1] + (weight_x2 * weight_y2) * src_data[int_srcy1*src_step + int_srcx1] +(weight_x1 * weight_y2) * src_data[int_srcy1*src_step + int_srcx2];
dst_data[y*dst_step + x] = (int)k;
}
}
}

代码实现图像:


0 0
原创粉丝点击