图像的缩放常用的有最邻近插值法,双线性内插法,和三次内插法。在opencv中对应的都是cvResize只是参数不一样,就想自己实现这个算法过程。
首先介绍一下这三种方法的大致思路:
最邻近插值法:f(i+u,i+v)就是通过判断u,v取整后的结果(比如u>0.5,v<0.5 取f(i+1,j)算法比较简单,但是放大后图像效果比较差;
双线性内插法是对四邻域内的四个像素点进行两个方向上进行插值处理,最后推导出来的表达式为: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)v+
f(i+1)f(v+1)*u*v
三次内插法是利用三次多项式逼近sin(x)/x对16个像素点进行插值。
这里只是将前两种方法的代码分享一下
方法一
int i,j,ni,nj;
IplImage *src;
IplImage *newimag;
CvSize n_size;
uchar **olddata;
uchar **newdata;
uchar *ptr_old;
uchar *ptr_new;
src=cvLoadImage("F://vc_source//picture_opencv//filter//lena.bmp");
n_size.height=src->height*scale;
n_size.width=src->width*scale;
newimag=cvCreateImage(n_size,src->depth,src->nChannels);
for(j=0;j<newimag->height;j++)
{ nj=(int)(j/scale);
ptr_old=(uchar *)(src->imageData+nj*src->widthStep);
ptr_new=(uchar *)(newimag->imageData+j*newimag->widthStep);
for(i=0;i<newimag->width;i++)
{ni=(int)(i/scale);
ptr_new[3*i]=ptr_old[3*ni];
ptr_new[3*i+1]=ptr_old[3*ni+1];
ptr_new[3*i+2]=ptr_old[3*ni+2];
}
}
printf("width is %d,widthStep is %d,channel is %d",newimag->width,newimag->widthStep,src->nChannels);
cvNamedWindow("p1");
cvNamedWindow("p2");
cvShowImage("p1",src);
cvShowImage("p2",newimag);
cvSaveImage("F://vc_source//picture_opencv//filter//lena1.bmp",newimag);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&newimag);
cvDestroyWindow("p1");
cvDestroyWindow("p2");
方法二
int i,j,oi,oj;
float ni,nj;
float u,v;
float temp[4];
IplImage *src;
IplImage *newimag;
CvSize n_size;
uchar **olddata;
uchar **newdata;
uchar *ptr_old1,*ptr_old;
uchar *ptr_new;
src=cvLoadImage("F://vc_source//picture_opencv//filter//lena.bmp");
n_size.height=src->height*scale;
n_size.width=src->width*scale;
newimag=cvCreateImage(n_size,src->depth,src->nChannels);
for(j=0;j<newimag->height;j++)
{ nj=(1.0*j)/scale;
oj=(int)nj;
v=fabs(nj-oj);
ptr_old=(uchar *)(src->imageData+oj*src->widthStep);
ptr_old1=(uchar *)(src->imageData+(oj+1)*src->widthStep);
ptr_new=(uchar *)(newimag->imageData+j*newimag->widthStep);
for(i=0;i<newimag->width;i++)
{ni=(1.0*i)/scale;
oi=(int)ni;
u=fabs(ni-oi);
temp[0]=(1.0-u)*(1.0-v);
temp[1]=(1.0-u)*v;
temp[2]=u*(1.0-v);
temp[3]=u*v;
ptr_new[3*i]=(int)(ptr_old[3*oi]*temp[0]+ptr_old1[3*oi]*temp[1]+ptr_old[3*(oi+1)]*temp[2]+ptr_old1[3*(oi+1)]*temp[3]);
ptr_new[3*i+1]= (int)(ptr_old[3*oi+1]*temp[0]+ptr_old1[3*oi+1]*temp[1]+ptr_old[3*(oi+1)+1]*temp[2]+ptr_old1[3*(oi+1)+1]*temp[3]);
ptr_new[3*i+2]= (int)(ptr_old[3*oi+2]*temp[0]+ptr_old1[3*oi+2]*temp[1]+ptr_old[3*(oi+1)+2]*temp[2]+ptr_old1[3*(oi+1)+2]*temp[3]);
//printf("B is %d,G is %d,R is %d\n",ptr_new[3*i],ptr_new[3*i+1],ptr_new[3*i+2]);
}
}
printf("width is %d,widthStep is %d,channel is %d",newimag->width,newimag->widthStep,src->nChannels);
cvNamedWindow("p1");
cvNamedWindow("p2");
cvShowImage("p1",src);
cvShowImage("p2",newimag);
cvSaveImage("F://vc_source//picture_opencv//filter//lena2.bmp",newimag);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&newimag);
cvDestroyWindow("p1");
cvDestroyWindow("p2");