图像旋转以及C代码实现
来源:互联网 发布:卡佩拉体测数据 编辑:程序博客网 时间:2024/06/05 06:17
原博客:http://blog.csdn.net/einsdrw/article/details/43525751
图像旋转就是将图像按一定角度旋转,依据当前点坐标计算出来的旋转后的坐标往不是整数,因此需要进行插值。常用的插值方法有最近邻插值法、线性插值法和样条插值法(这个我也不懂)。最近邻插值速度快,效果差;双向性插值法效果较好,速度还行。这里只讨论使用反向映射和双线性插值的图像旋转。
旋转原理:
反向映射就是依据旋转后图像中的坐标,求出其在原图像中的坐标。
如图,将图像逆时针旋转一个角度
计算旋转后图像时就可以利用(3)式用旋转后的坐标计算其在原图中的坐标,并利用附近的像素插值的到当前的像素值。
图像的原点一般在左上角,这样计算出来的坐标会有负值,一般将图像原点平移到图像中心。记原图像的宽高为srcW、srcH,旋转后图像宽高为dstW、dstH,那么(3)式就变为:
双线性插值
由旋转后图像坐标计算出来的原图像坐标往往不是整数,为了保证旋转效果,进行双线性插值。双线性插值就是对两个变量的线性插值,分别对每个变量线性插值就得到最终的插值结果。
详细资料参考
http://www.cnblogs.com/linkr/p/3630902.html
代码如下,使用opencv加载图像。
调用方法
void main(int argc, char** argv){IplImage* iplOrg=cvLoadImage(argv[1]);//加载图像unsigned char* pColorImg=NULL;int width=iplOrg->width;int height=iplOrg->height;pColorImg=(unsigned char*)malloc(width*height*3*sizeof(unsigned char));cvCvtColor(iplOrg,iplOrg,CV_BGR2RGB);IplToUchar(iplOrg,pColorImg);//用数组表示图像cvReleaseImage(&iplOrg);double degree=15;//逆时针旋转角度0~180int tempLength=sqrt((double)width * width + (double)height *height) + 10;//保证原图可以任意角度旋转的最小尺寸unsigned char* pTemp=(unsigned char*)malloc(tempLength*tempLength*3*sizeof(unsigned char));//旋转myImgRotate(pColorImg,width,height,pTemp,tempLength,tempLength,degree,3);DisplayPicture(tempLength,tempLength,pTemp,"rotate.bmp",3);//保存图像free(pTemp);pTemp=NULL;free(pColorImg);pColorImg=NULL;}旋转函数
//逆时针旋转到pdst的中心,其它用0填充//pSrc,srcW,srcH原图及其尺寸//pDst,dstW,dstH旋转后图像及其尺寸//旋转角度//通道数void myImgRotate(unsigned char* pSrc,int srcW,int srcH, unsigned char* pDst,int dstW,int dstH, double degree,int nchannel){int k;double angle = degree * 3.1415926 / 180.;//旋转角度double co=cos(angle);//余弦double si=sin(angle);//正弦int rotateW,rotateH;//旋转后图像的高宽int srcWidthStep=srcW*nchannel;//宽度步长int dstWisthStep=dstW*nchannel;int x,y;int xMin,xMax,yMin,yMax;int xOff,yOff;//偏移double xSrc=0.;double ySrc=0.;//变换后图像的坐标在原图中的坐标//临时变量float valueTemp=0.;float a1,a2,a3,a4;memset(pDst,0,dstWisthStep*dstH*sizeof(unsigned char));//计算旋转后的坐标范围rotateH=srcW*fabs(si)+srcH*fabs(co);rotateW=srcW*fabs(co)+srcH*fabs(si);//计算偏移xOff=dstW/2;yOff=dstH/2;yMin=(dstH-rotateH)/2.;yMax=yMin+rotateH+1;//加1xMin=(dstW-rotateW)/2.;xMax=xMin+rotateW+1;for (y=yMin;y<=yMax;y++){for (x=xMin;x<=xMax;x++){//求取在原图中的坐标ySrc=si*double(x-xOff)+co*double(y-yOff)+double(int(srcH/2));xSrc=co*double(x-xOff)-si*double(y-yOff)+double(int(srcW/2));//如果在原图范围内if (ySrc>=0. && ySrc<srcH-0.5 && xSrc>=0. && xSrc<srcW-0.5){//插值int xSmall=floor(xSrc);int xBig=ceil(xSrc);int ySmall=floor(ySrc);int yBig=ceil(ySrc);for (k=0;k<nchannel;k++){a1=(xSmall>=0 && ySmall>=0 ? pSrc[ySmall*srcWidthStep+xSmall*nchannel+k]:0);a2=(xBig<srcW && ySmall>=0 ? pSrc[ySmall*srcWidthStep+xBig*nchannel+k]:0);a3=(xSmall>=0 && yBig<srcH ? pSrc[yBig*srcWidthStep+xSmall*nchannel+k]:0);a4=(xBig<srcW && yBig<srcH ? pSrc[yBig*srcWidthStep+xBig*nchannel+k]:0);double ux=xSrc-xSmall;double uy=ySrc-ySmall;//双线性插值valueTemp=(1-ux)*(1-uy)*a1+(1-ux)*uy*a3+(1-uy)*ux*a2+ux*uy*a4;pDst[y*dstWisthStep+x*nchannel+k]=floor(valueTemp);}}}}}
结果
参考资料
http://blog.csdn.net/xiaowei_cqu/article/details/7616044
http://www.cnblogs.com/mlv5/archive/2012/02/02/2336321.html
http://www.cnblogs.com/slysky/archive/2012/03/21/2410743.html
http://blog.csdn.net/jia20003/article/details/8221173
- 图像旋转以及C代码实现
- 图像旋转以及C代码实现
- 最近邻图像旋转代码 灰度图像 c++实现
- 求旋转数组的最小数字算法的解析以及完整c语言代码实现
- 图像旋转代码
- python图像旋转代码
- 全局块匹配法计算图像旋转以及实现程序
- Opencv实现图像旋转,非常简单,几行代码
- MATLAB实现基于邻近插值的图像旋转代码
- j2me实现图像旋转
- opencv实现图像旋转
- opencv实现图像旋转
- Opencv实现图像旋转
- OpenCV实现图像旋转
- opencv实现图像旋转
- opencv实现图像旋转
- 图像旋转的实现
- opencv实现图像旋转
- tensorflow 版本查看命令
- 二叉树的某些性质
- JAVA变量初始化的默认值
- 输出一个爱心
- form is not define的原因-JavaScript
- 图像旋转以及C代码实现
- 操作系统常用调度算法
- android ndk cmake c++调用c语言函数
- CentOS系统MySql的安装步骤
- 第四章:git add , git commit 添加错文件 撤销
- Windows下Anaconda的安装和简单使用
- bzoj 3212: Pku3468 A Simple Problem with Integers
- Nicescroll滚动条插件的用法
- js-dom-使用错误记录