图像旋转以及C代码实现

   图像旋转就是将图像按一定角度旋转,依据当前点坐标计算出来的旋转后的坐标往不是整数,因此需要进行插值。常用的插值方法有最近邻插值法、线性插值法和样条插值法(这个我也不懂)。最近邻插值速度快,效果差;双向性插值法效果较好,速度还行。这里只讨论使用反向映射和双线性插值的图像旋转。

旋转原理:

反向映射就是依据旋转后图像中的坐标,求出其在原图像中的坐标。

如图,将图像逆时针旋转一个角度

 

    计算旋转后图像时就可以利用(3)式用旋转后的坐标计算其在原图中的坐标,并利用附近的像素插值的到当前的像素值。

    图像的原点一般在左上角,这样计算出来的坐标会有负值,一般将图像原点平移到图像中心。记原图像的宽高为srcW、srcH,旋转后图像宽高为dstW、dstH,那么(3)式就变为:

 

双线性插值

    由旋转后图像坐标计算出来的原图像坐标往往不是整数,为了保证旋转效果,进行双线性插值。双线性插值就是对两个变量的线性插值,分别对每个变量线性插值就得到最终的插值结果。

详细资料参考

http://www.cnblogs.com/linkr/p/3630902.html

 

代码如下,使用opencv加载图像。

调用方法

[cpp]  view plain  copy
  1. void main(int argc, char** argv)  
  2. {  
  3.     IplImage* iplOrg=cvLoadImage(argv[1]);  //加载图像  
  4.     unsigned char* pColorImg=NULL;  
  5.     int width=iplOrg->width;  
  6.     int height=iplOrg->height;  
  7.     pColorImg=(unsigned char*)malloc(width*height*3*sizeof(unsigned char));  
  8.   
  9.     cvCvtColor(iplOrg,iplOrg,CV_BGR2RGB);  
  10.     IplToUchar(iplOrg,pColorImg);   //用数组表示图像  
  11.     cvReleaseImage(&iplOrg);  
  12.   
  13.     double degree=15;   //逆时针旋转角度0~180  
  14.   
  15.     int tempLength=sqrt((double)width * width + (double)height *height) + 10;//保证原图可以任意角度旋转的最小尺寸  
  16.     unsigned char* pTemp=(unsigned char*)malloc(tempLength*tempLength*3*sizeof(unsigned char));  
  17.   
  18.           
  19.     //旋转  
  20.     myImgRotate(pColorImg,width,height,pTemp,tempLength,tempLength,degree,3);  
  21.     DisplayPicture(tempLength,tempLength,pTemp,"rotate.bmp",3); //保存图像  
  22.       
  23.     free(pTemp);  
  24.     pTemp=NULL;  
  25.     free(pColorImg);  
  26.     pColorImg=NULL;  
  27.       
  28. }  


 

旋转函数

[cpp]  view plain  copy
  1. //逆时针旋转到pdst的中心,其它用0填充  
  2. //pSrc,srcW,srcH原图及其尺寸  
  3. //pDst,dstW,dstH旋转后图像及其尺寸  
  4. //旋转角度  
  5. //通道数  
  6. void myImgRotate(unsigned char* pSrc,int srcW,int srcH,  
  7.                            unsigned char* pDst,int dstW,int dstH,  
  8.                            double degree,int nchannel)  
  9. {  
  10.   
  11.     int k;  
  12.     double angle = degree  * 3.1415926 / 180.;  //旋转角度  
  13.     double co=cos(angle);   //余弦  
  14.     double si=sin(angle);   //正弦  
  15.     int rotateW,rotateH;    //旋转后图像的高宽  
  16.     int srcWidthStep=srcW*nchannel;//宽度步长  
  17.     int dstWisthStep=dstW*nchannel;   
  18.     int x,y;  
  19.     int xMin,xMax,yMin,yMax;  
  20.     int xOff,yOff;  //偏移  
  21.     double xSrc=0.;  
  22.     double ySrc=0.; //变换后图像的坐标在原图中的坐标  
  23.   
  24.     //临时变量  
  25.     float valueTemp=0.;  
  26.     float a1,a2,a3,a4;  
  27.   
  28.     memset(pDst,0,dstWisthStep*dstH*sizeof(unsigned char));  
  29.     //计算旋转后的坐标范围  
  30.     rotateH=srcW*fabs(si)+srcH*fabs(co);  
  31.     rotateW=srcW*fabs(co)+srcH*fabs(si);  
  32.   
  33.     //计算偏移  
  34.     xOff=dstW/2;  
  35.     yOff=dstH/2;  
  36.   
  37.     yMin=(dstH-rotateH)/2.;  
  38.     yMax=yMin+rotateH+1;    //加1  
  39.     xMin=(dstW-rotateW)/2.;  
  40.     xMax=xMin+rotateW+1;  
  41.   
  42.     for (y=yMin;y<=yMax;y++)  
  43.     {  
  44.         for (x=xMin;x<=xMax;x++)  
  45.         {  
  46.             //求取在原图中的坐标  
  47.             ySrc=si*double(x-xOff)+co*double(y-yOff)+double(int(srcH/2));  
  48.             xSrc=co*double(x-xOff)-si*double(y-yOff)+double(int(srcW/2));  
  49.               
  50.             //如果在原图范围内  
  51.             if (ySrc>=0. && ySrc<srcH-0.5 && xSrc>=0. && xSrc<srcW-0.5)  
  52.             {  
  53.                 //插值  
  54.                 int xSmall=floor(xSrc);  
  55.                 int xBig=ceil(xSrc);  
  56.                 int ySmall=floor(ySrc);  
  57.                 int yBig=ceil(ySrc);  
  58.   
  59.                 for (k=0;k<nchannel;k++)  
  60.                 {  
  61.                     a1=(xSmall>=0 && ySmall>=0 ? pSrc[ySmall*srcWidthStep+xSmall*nchannel+k]:0);  
  62.                     a2=(xBig<srcW && ySmall>=0 ? pSrc[ySmall*srcWidthStep+xBig*nchannel+k]:0);  
  63.                     a3=(xSmall>=0 && yBig<srcH ? pSrc[yBig*srcWidthStep+xSmall*nchannel+k]:0);  
  64.                     a4=(xBig<srcW && yBig<srcH ? pSrc[yBig*srcWidthStep+xBig*nchannel+k]:0);  
  65.                     double ux=xSrc-xSmall;  
  66.                     double uy=ySrc-ySmall;  
  67.                     //双线性插值  
  68.                     valueTemp=(1-ux)*(1-uy)*a1+(1-ux)*uy*a3+(1-uy)*ux*a2+ux*uy*a4;  
  69.                     pDst[y*dstWisthStep+x*nchannel+k]=floor(valueTemp);  
  70.                 }  
  71.   
  72.             }  
  73.         }  
  74.     }  
  75. }  


结果

     

猜你喜欢

转载自blog.csdn.net/zouli415/article/details/80082432