《Computer Vision:Algorithms and Applications》学习笔记(一)——图像旋转算法与实现
2012-02-02 22:16
489 查看
昨天和今天学习了《Computer Vision:Algorithms and Applications》中第二章“Image formation”前半部分,主要是如何表示2D、3D图像中的点、线、面等,以及如何用公式推导出2D图形的几何变换,如位移、旋转、放缩、仿射变换、投射等,如下图所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/188cd68aed5721f6368d1e36494bc51d.jpg)
一、图像旋转方法简介
其中的图像旋转是一种常用的数字图像处理技术。由于旋转后图像像素点坐标不再是整数,所以旋转后必须对新的像素点灰度值进行插值运算。目前常用的方法有最近邻插值法、线性插值法和样条插值法。文献介绍,最近邻法速度快,方法简单,但生成图像效果较差;样条插值法计算精度高,效果好,但计算复杂,速度较慢;线性插值法(E.g. 双线性插值法)效果较好,运行时间较短。另外,实现赋值的方法分为正向映射法和反向映射法:正向映射法是指,从原始图像坐标出发,计算出在旋转图像上坐标,然后将原始图像该坐标的灰度值赋给对应旋转图像该坐标点;反向映射法则反之。
本文将分别采用基于最近邻取值的正向映射法、基于最近邻取值的反向映射法、基于双线性插值的反向映射法实现图像旋转,并对比三种方法的效果。
二、本文方法
1. 基于最近邻取值的正向映射法
这种方法最简单,也最直观,先考虑图像旋转原理:
以顺时针旋转为例来堆到旋转变换公式。如下图所示。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/aec0848fbc76d2f47b8104f29c90180c.jpg)
旋转前:
x0=rcosb;y0=rsinb
旋转a角度后:
x1=rcos(b-a)=rcosbcosa+rsinbsina=x0cosa+y0sina
y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa
正向映射即根据原图的坐标推导出旋转图像对应点坐标,然后直接将原图坐标灰度值赋给x1,y1
2.基于最近邻取值的反向映射法
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/d42f99bbbdadc5b88a0e68dd5ad4148e.jpg)
旋转前:
x1=rcosc;y1=rsinc
旋转a角度后:
x0=rcos(c+a)=rcosccosa-rsincsina=x1cosa-y1sina
y0=rsin(c+a)=rsinccosa+rcoscsina=-x1sina+y1cosa
反向映射即已知旋转后图像坐标,通过公式推导出原始图像上对应坐标,将该坐标对应灰度值赋给旋转后坐标。因为计算得到的y0, x0非整数,最近邻方法即将与(Xo,Yo)距离最近的像素的灰度值作为(Xo,Yo)的灰度值赋给(X1,Y1)点。
3.基于双线性插值的反向映射法
在计算(Xo,Yo)的灰度值时,采用如下方法计算:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/c579079773a79195630a9a60d7266bb5.jpg)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/66ec618da9e2ebfcc3942ff45ca3a9e3.jpg)
三、实验对比
三种实验结果的对比图如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/e82a76575339e7db3570a9eab83b7beb.jpg)
可见,双线性插值法获得的旋转图像更平滑,接近真实图像。
三种方法的matlab代码如下
参考文献:
1. 《Computer Vision:Algorithms and Applications》,pp30-40
2. 曹佃国, 陈浩杰,李鹏, "基于 Matlab 的双线性插值算法在图像旋转中的应用".
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/188cd68aed5721f6368d1e36494bc51d.jpg)
一、图像旋转方法简介
其中的图像旋转是一种常用的数字图像处理技术。由于旋转后图像像素点坐标不再是整数,所以旋转后必须对新的像素点灰度值进行插值运算。目前常用的方法有最近邻插值法、线性插值法和样条插值法。文献介绍,最近邻法速度快,方法简单,但生成图像效果较差;样条插值法计算精度高,效果好,但计算复杂,速度较慢;线性插值法(E.g. 双线性插值法)效果较好,运行时间较短。另外,实现赋值的方法分为正向映射法和反向映射法:正向映射法是指,从原始图像坐标出发,计算出在旋转图像上坐标,然后将原始图像该坐标的灰度值赋给对应旋转图像该坐标点;反向映射法则反之。
本文将分别采用基于最近邻取值的正向映射法、基于最近邻取值的反向映射法、基于双线性插值的反向映射法实现图像旋转,并对比三种方法的效果。
二、本文方法
1. 基于最近邻取值的正向映射法
这种方法最简单,也最直观,先考虑图像旋转原理:
以顺时针旋转为例来堆到旋转变换公式。如下图所示。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/aec0848fbc76d2f47b8104f29c90180c.jpg)
旋转前:
x0=rcosb;y0=rsinb
旋转a角度后:
x1=rcos(b-a)=rcosbcosa+rsinbsina=x0cosa+y0sina
y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa
正向映射即根据原图的坐标推导出旋转图像对应点坐标,然后直接将原图坐标灰度值赋给x1,y1
2.基于最近邻取值的反向映射法
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/d42f99bbbdadc5b88a0e68dd5ad4148e.jpg)
旋转前:
x1=rcosc;y1=rsinc
旋转a角度后:
x0=rcos(c+a)=rcosccosa-rsincsina=x1cosa-y1sina
y0=rsin(c+a)=rsinccosa+rcoscsina=-x1sina+y1cosa
反向映射即已知旋转后图像坐标,通过公式推导出原始图像上对应坐标,将该坐标对应灰度值赋给旋转后坐标。因为计算得到的y0, x0非整数,最近邻方法即将与(Xo,Yo)距离最近的像素的灰度值作为(Xo,Yo)的灰度值赋给(X1,Y1)点。
3.基于双线性插值的反向映射法
在计算(Xo,Yo)的灰度值时,采用如下方法计算:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/c579079773a79195630a9a60d7266bb5.jpg)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/66ec618da9e2ebfcc3942ff45ca3a9e3.jpg)
三、实验对比
三种实验结果的对比图如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201202/e82a76575339e7db3570a9eab83b7beb.jpg)
可见,双线性插值法获得的旋转图像更平滑,接近真实图像。
三种方法的matlab代码如下
Image=imread('E:\1.jpg'); %X,Y为其行列数 angle=30; %角度任意的一个数 表示30度 pai=3.1415929657; Angle=pai*angle/180; %转换一下角度的表示方法。 [Y,X,Z]=size(Image); %原图显示 subplot(2,2,1); imshow(Image); title('原图像'); % %计算四个角点的新坐标,确定旋转后的显示区域 LeftBottom(1,1)=(Y-1)*sin(Angle); LeftBottom(1,2)=(Y-1)*cos(Angle); LeftTop(1,1)=0; LeftTop(1,2)=0; RightBottom(1,1)=(X-1)*cos(Angle)+(Y-1)*sin(Angle); RightBottom(1,2)=-(X-1)*sin(Angle)+(Y-1)*cos(Angle); RightTop(1,1)=(X-1)*cos(Angle); RightTop(1,2)=-(X-1)*sin(Angle); %计算显示区域的行列数 Xnew=max([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])-min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)]); Ynew=max([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)])-min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)]); % 分配新显示区域矩阵 ImageNewForward=zeros(round(Ynew),round(Xnew),3)+255; ImageNewIntersection=zeros(round(Ynew),round(Xnew),3)+255; ImageNew1nn=zeros(round(Ynew),round(Xnew),3)+255; %计算原图像各像素的新坐标:正向映射法 for indexX=0:(X-1) for indexY=0:(Y-1) Yn=1+round(-indexX*sin(Angle)+indexY*cos(Angle))+round(abs(min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)]))); Xn=round(indexX*cos(Angle)+indexY*sin(Angle))+round(abs(min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])))+1; ImageNewForward(Yn,Xn,1)=Image(indexY+1,indexX+1,1); ImageNewForward(Yn,Xn,2)=Image(indexY+1,indexX+1,2); ImageNewForward(Yn,Xn,3)=Image(indexY+1,indexX+1,3); end end %%反向映射法 for indexY=1:round(Ynew) for indexX=1:round(Xnew) Y1=indexY-round(abs(min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)]))); X1=indexX-round(abs(min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)]))); Yoo=X1*sin(Angle)+Y1*cos(Angle); Xoo=X1*cos(Angle)-Y1*sin(Angle); Yo=round(Yoo); Xo=round(Xoo); if 1<Xo&&Xo<X&&1<Yo&&Yo<Y %最近邻法 ImageNew1nn(indexY,indexX,1)=Image(Yo,Xo,1); ImageNew1nn(indexY,indexX,2)=Image(Yo,Xo,2); ImageNew1nn(indexY,indexX,3)=Image(Yo,Xo,3); %双线性插值法 left=floor(Xoo); right=ceil(Xoo); up=floor(Yoo); down=ceil(Yoo); upmid1=(1-Xoo+left)*Image(up,left,1)+(Xoo-left)*Image(up,right,1); downmid1=(1-Xoo+left)*Image(down,left,1)+(Xoo-left)*Image(down,right,1); upmid2=(1-Xoo+left)*Image(up,left,2)+(Xoo-left)*Image(up,right,2); downmid2=(1-Xoo+left)*Image(down,left,2)+(Xoo-left)*Image(down,right,2); upmid3=(1-Xoo+left)*Image(up,left,3)+(Xoo-left)*Image(up,right,3); downmid3=(1-Xoo+left)*Image(down,left,3)+(Xoo-left)*Image(down,right,3); central1=(1-Yoo+up)*upmid1+(Yoo-up)*downmid1; central2=(1-Yoo+up)*upmid2+(Yoo-up)*downmid2; central3=(1-Yoo+up)*upmid3+(Yoo-up)*downmid3; ImageNew(indexY,indexX,1)=central1; ImageNew(indexY,indexX,2)=central2; ImageNew(indexY,indexX,3)=central3; else ImageNew(indexY,indexX,:)=255; end end end %显示 subplot(2,2,2); ImageNewForward=uint8(ImageNewForward); imshow(ImageNewForward); promp=['旋转角度为:' int2str(angle) '度图像 正向映射法']; title(promp); subplot(2,2,3); ImageNew1nn=uint8(ImageNew1nn); imshow(ImageNew1nn); promp=['旋转角度为:' int2str(angle) '度图像 最近邻插值法']; title(promp); subplot(2,2,4); ImageNew=uint8(ImageNew); imshow(ImageNew); promp=['旋转角度为:' int2str(angle) '度图像 双线性插值法']; title(promp);
参考文献:
1. 《Computer Vision:Algorithms and Applications》,pp30-40
2. 曹佃国, 陈浩杰,李鹏, "基于 Matlab 的双线性插值算法在图像旋转中的应用".
相关文章推荐
- Computer Vision: Algorithms and Applications 计算机视觉:算法与应用 翻译工作 序
- 《Computer Vision:Algorithms and Applications》计算机视觉 算法与应用 学习系列 目录
- Computer Vision & Algorithms and Applications 计算机视觉-算法与应用 - 中文 完整书签
- 快速图像旋转算法的c++实现
- Computer Vision: Algorithms and Applications(学习笔记一)--introduction
- 图像旋转算法与实现
- 图像旋转算法与实现
- 图像旋转算法与实现
- 基于《Combining Sketch and Tone for Pencil Drawing Production》的图像铅笔画算法的实现
- 图像旋转算法与实现
- Computer Vision:Algorithms and Applications (Image stitching)
- Computer Vision: Algorithms and Applications(学习笔记二)--geometric transformations
- 图像旋转算法与实现
- 图像旋转算法与实现
- Computer Vision: Algorithms and ApplicationsのImage processing
- opencv实现图像任意角度旋转的算法解析及代码实现
- OpenCV中图像旋转(warpAffine)算法的实现过程
- OpenCV中图像旋转(warpAffine)算法的实现过程
- OpenCV中图像旋转(warpAffine)算法的实现过程
- 用OpenCV实现Photoshop算法(一): 图像旋转