图像的几何变换的两种实现旋转平移放大缩小Word格式文档下载.docx
《图像的几何变换的两种实现旋转平移放大缩小Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《图像的几何变换的两种实现旋转平移放大缩小Word格式文档下载.docx(35页珍藏版)》请在冰豆网上搜索。
这就需要进行一定的畸变校正。
在进行目标物的匹配时,需要对图像进行旋转、平移等处理。
在进行三维景物显示时,需要进行三维到二维平面的投影建模。
因此,图像几何变换是图像处理及分析的基础。
图像几何变换是计算机图像处理领域中的一个重要组成部分,也是值得深讨的一个重要课题。
在图像几何变换中主要包括图像的放缩、图像的旋转、图像的移动、图像的镜像、图像的块操作等容,几何变换不改变图像的像素值,只改变像素所在的几何位置。
从广义上说,图像是自然界景物的客观反映,是人类认识世界和人类本身的重要源泉。
图像对我们并不陌生。
我们生活在一个信息时代,科学研究和统计表明,人类从外界获得的信息约有75%来自视觉系统,也就是从图像中获得的。
所以对数字图像的处理便显得尤为重要了。
本文主要深讨了图像的几何变换(主要包括图像的平移、转置、缩放、旋转、镜像等)理论,并在此基础上用VisualC++实现的过程。
1.3.2研究方法
方法一:
利用Windows本身就提供了一个API函数SetWorldTransForm来实现图片旋转、位移及其他变形,这个函数是对一个设备上下文DC进行操作,通过坐标转换来实现各种功能的。
方法二:
通过图像进行平移、旋转、转置、镜像、缩放后重新计算各点新像素完成几何变换。
自定义一个图像处理的Cdibapi类,把一般处理图像时要用到的函数实现封装在这个类中,该类用于实现DIB对象的绘制,DIB对象调色板的创建,DIB对象的读取与存储,图像线性变换,图像灰度拉伸等。
然后把在视类中实现图像平移,图像镜像,图像转置,图像缩放及图像旋转的函数调用和实现。
二、正文
2.1灰度图
灰度图(Grayscale)是指只含亮度信息,不含色彩信息的图像。
因此,要表示灰度图,就需要把亮度值进行量化。
通常划分为0到255共256个级别,0最暗(全黑),255最亮(全白)。
BMP格式的文件中并没有灰度图这个概念,但是可以很容易的用BMP文件来表示灰度图。
方法是用256色的调色板,只不过这个调色板有点特殊,每一项的RGB值都是相同的。
也就是说RGB值从(0,0,0),(1,1,1)一直到(255,255,255)。
(0,0,0)是全黑色,(255,255,255)是全白色,中间的是灰色。
2.2调色板
调色板结构LOGPALETTE,该结构定义如下:
typedefstructtagLOGPALETTE
{
WORDpalVersion;
//调色板的板本号,应该指定该值为0x300;
WORDpalNumEntries;
//调色板中的表项数,对于灰度图像该值为256;
PALETEENTRYpalPalEntry[1];
//调色板中的颜色表项,由于该表项的数
目不一定,所以这里数组长度定义为1,灰度图像对应的该数组的长度为256
}LOGPALETTE;
颜色表项结构PALETTEENTRY定义了调色板中的每一个颜色表项的颜色和使用方式,定义如下:
typedefstructtagPALETTEENTRY
BYTEpeRed;
//R分量值;
BYTEpeGreen;
//G分量值;
BYTEpeBlue;
//B分量值;
BYTEpeFlags;
//该颜色被使用的方式,一般情况下设为"
0"
;
}PALETTEENTRY;
Windows系统使用调色板管理器来管理与调色板有关的操作,通常活动窗口的调色板即是当前系统调色板,所有的非活动窗口都必须按照此系统调色板来显示自己的颜色,此时调色板管理器将自动的用系统调色板中的最近似颜色来映射相应的显示颜色。
如果窗口或应用程序按自己的调色板显示颜色,就必须将自己的调色板载入到系统调色板中,
这种操作叫作实现调色板,实现调色板包括两个步骤:
1.
首先将调色板选择到设备上下文中,可以通过CDC:
:
SelectPalette()选入设备上下文
2.
然后在设备上下文中实现调色板,可以通过CDC:
RealizePalette()实现设备调色板。
1.2.4BMP文件中DIB的结构
DIB是标准的Windows位图格式,BMP文件中包含了一个DIB。
一个BMP文件大体上分成如下4个部分:
BITMAPFILEHEADER
位图文件头
(只用于BMP文件)
BITMAPINFOHEADER
位图信息头
Palette
调色板
DIBPirxels
DIB图像数据
2.3图像的几何变换基础知识
图像的几何变换,通常包括图像的平移、图像的镜像变换、图像的转置、图像的缩放和图像的旋转等。
图2.1程序基本框架图
2.3.1图像的平移
图像的平移是几何变换中最简单的变换之一。
图像平移就是将图像中所有的点都按照指定的平移量水平、垂直移动。
设(x0,y0)坐标将变为(x1,y1)。
显然(x0,y0)和(x1,y1)的关系如下:
用矩阵表示如下:
对该矩阵求逆,可以得到逆变换:
这样,平移后的图像上的每一点都可以在原图像中找到对应的点。
例如,
对于新图中的(0,0)像素,代入上面的方程组,可以求出对应原图中的像素(-tx,-ty)。
如果tx或ty大于0,则(-tx,-ty)不在原图中。
对于不在原图中的点,可以直接将它的像素值统一设置为0或则255(对于灰度图就是黑色或白色)。
同样,若有点不在原图中,也就说明原图中有点被移出显示区域。
如果不想丢失被移出的部分图像,可以将新生成的图像宽度扩大|tx|,高度扩大|ty|。
2.3.2图像的镜像
图像的镜像变换分为两种:
一种是水平镜像,另外一种是垂直镜像。
图像的水平镜像操作是将图像的左半部分和右半部分以图像垂直中轴线为中心镜像进行对换;
图像的垂直镜像操作是将图像上半部分和下半部分以图像水平中轴线为中心镜像进行对换。
设图像高度为lHeight,宽度为lWidth,原图中(x0,y0)经过水平镜像后坐标将变为(lWidth-x0,y0),其矩阵表达式为:
逆运算表达式为:
即
同样,(x0,y0)经过垂直镜像后坐标将变为(x0,lHeight-y0),其矩阵表
达式为:
逆运算矩阵表达式为:
即
2.3.3图像的转置
图像的转置操作是将图像像素的x坐标和y坐标互换。
该操作将改变图像的大小,图像的高度和宽度将互换。
转置表达式:
它的逆矩阵表达式:
2.3.4图像的缩放
上面的几种图像几何变换中都是1:
1的变换,而图像的缩放操作将会改变图像的大小,产生的图像中的像素可能在原图中找不到相应的像素点,这样就必须进行近似处理。
一般的方法是直接赋值为和它最相近的像素值,也可以通过一些插值算法来计算。
下面的代码直接采用了前一种做法。
假设图像x轴方向缩放比率为fx,y轴方向缩放比率为fy,那么原图中点(x0,y0)对应与新图中的点(x1,y1)的转换矩阵为:
其逆运算如下:
例如,当fx=fy=0.5时,图像被缩放到一半大小,此时缩小后图像中的(0,0)像素对应于原图中的(0,0)像素;
(0,1)像素对应于原图中的(0,2)像素;
(1,0)像素对应于原图中的(2,0)像素,以此类推。
在原图基础上,每行隔一个像素取一点,每隔一行进行操作。
其实是将原图每行中的像素重复取值一遍,然后每行重复一次。
2.3.5图像的旋转
一般图像的旋转是以图像的中心为原点,旋转一定的角度。
旋转后,图像的大小一般会改变。
和图像平移一样,既可以把转出显示区域的图像截去,也可以扩大图像围以显示所有的图像。
可以推导一下旋转运算的变换公式。
如下图所示,点(x0,y0)经过旋转θ度后坐标变成(x1,y1)。
在旋转前:
转置后:
写成矩阵表达式为:
有了上面的转换公式,就可以非常方便的编写出实现图像旋转的函数。
首先应计算出公式中需要的几个参数:
a,b,c,d和旋转后新图像的高、宽度。
现在已知图像的原始宽度为lWidth,高度为lHeight,以图像中心为坐标系原点,则原
始图像四个角的坐标分别为
和
,按照旋转公式,在旋转后的新图中,这四个点坐标为:
则新图像的宽度lNewWidth和高度lNewHeight为:
lNewWidth=max
lNewHeight=max
令
,其中
,则
2.4Visual
C++简述
VisualC++是微软公司提供的基于C/C++的应用程序集成开发工具。
VC拥有丰富的功能和大量的扩展库,使用它能有效的创建高性能的Windows应用程序和Web应用程序。
VC的优越性主要表现在以下几个方面:
开发分布式应用、开发的应用程序运行效率高、具有健壮性、能缩短软件升级周期。
能够生成多线程应用,而多线程应用对于增加并发响应有实际意义。
VC除了提供高效的C/C++编译器外,还提供了大量的可重用类和组件,包括著名的微软基础类库(MFC)和活动模板类库(ATL),因此它是软件开发人员不可多得的开发工具。
将Visual
C++应用于数字图像的几何变换,VC丰富的功能和大量的扩展库,类的重用特性以及它对函数库、DLL库的支持能使程序更好的模块化,并且通过向导程序大大简化了库资源的使用和应用程序的开发,正由于VC具有明显的优势,因而我选择了它来作为数字图像几何变换的开发工具。
在本程序的开发过程中,VC的核心知识、消息映射机制、对话框控件编程等都得到了生动的体现和灵活的应用。
三、实验步骤及结果
3.1通过API函数SetWorldTransForm实现图像几何变换
API函数SetWorldTransForm实现图像几何变换使用XFORM来控制DC时,需要先设置绘图模式SetGraphicsMode为GM_ADVANCED,再用SetWorldTransform。
否则SetWorldTransform函数会失败。
setWorldTransForm部的算法其实相当于用线性代数里矩阵与一个向量相乘的办法来解决图形的变换,只要我们知道要乘上的变换方程是哪一个,就能进行各种变换(不止是旋转),这个函数是对一个设备上下文DC进行操作,通过坐标转换来实现各种功能的。
函数原型:
intSetGraphicsMode(HDChdc,intiMode);
参数:
hdc:
指向设备环境的句柄。
iMode:
指定图形模式,该参数取值参看MSDN
BOOLSetWorldTransform(HDChdc,CONSTXFORM*lpXform);
lpxform:
指向XFORM结构的指针,此结构含有转换数据。
返回值:
如果函数调用成功,返回值为非零值,否则为零。
编程原理:
对于选定DC的任何坐标(x,y)将被SetWindowsForm设定的变换转换为坐标(x’,y’),两个坐标的对应关系是:
x’
=
x
*
eM11
+
y
eM12
eDx;
y’
eM22
eDy;
对于一个转换的操作,数学上的转换方式是:
x2
cos(q)*(x1-x0)
–
sin(q)*(y1-y0)
x0;
y2
sin(q)*(x1-x0)
cos(q)*(y1-y0)
y0;
于是,我们可以得到SetWorldTransForm的一组参数:
xform.eM11
cos(q);
xform.eM12
sin(q);
xform.eM21
-sin(q);
xform.eM22
xform.eDx
x0-cos(q)*x0+sin(q)*y0;
xform.eDy
y0-cos(q)*y0-sin(q)*x0;
实验步骤:
一、先新建一个对话框的应用程序;
二、修改对话框的属性将其Caption属性改为“图片处理”,Border属性改为“Resizing”,为其添加一些控件并未其中的而一些控件关联变量且修改控件的属性如图:
三、为旋转、缩放、平移控件添加消息处理及绘制矩形和椭圆、旋转DC等代码
3.1.1图像旋转的代码及结果:
if(m_iAngle!
=0)
{
fangle=(double)m_iAngle/180.*3.1415926;
xform.eM11=(float)cos(fangle);
xform.eM12=(float)sin(fangle);
xform.eM21=(float)-sin(fangle);
xform.eM22=(float)cos(fangle);
xform.eDx=(float)(centerPt.x-cos(fangle)*centerPt.x+sin(fangle)*centerPt.y);
xform.eDy=(float)(centerPt.y-cos(fangle)*centerPt.y-sin(fangle)*centerPt.x);
SetWorldTransform(hDc,&
xform);
}
实验结果:
旋转前图像旋转
的图像
旋转
的图像旋转
的图像
3.1.2图像缩放的代码及结果
试验代码:
if(m_iSize!
=1)
xform.eM11=m_iSize*(float)cos(fangle);
xform.eM12=m_iSize*(float)sin(fangle);
xform.eM21=m_iSize*(float)-sin(fangle);
xform.eM22=m_iSize*(float)cos(fangle);
xform.eDx=(float)(centerPt.x-m_iSize*cos(fangle)*centerPt.x+m_iSize*sin(fangle)*centerPt.y+m_iPanLeft);
xform.eDy=(float)(centerPt.y-m_iSize*cos(fangle)*centerPt.y-m_iSize*sin(fangle)*centerPt.x+m_iPanRight);
缩放前的图像放大2.5倍的图像
缩小0.5倍的图像放大2.5倍且旋转
3.1.3图像平移的代码及结果
实验代码:
if(m_iPanLeft!
=0||m_iPanRight!
=0)
xform.eDx=(float)(centerPt.x-cos(fangle)*centerPt.x+sin(fangle)*centerPt.y+m_iPanLeft);
xform.eDy=(float)(centerPt.y-cos(fangle)*centerPt.y-sin(fangle)*centerPt.x+m_iPanRight);
平移前的图像横向平移56.5纵向平移45的图像
横向平移56纵向平移45且旋转
横向平移-56纵向平移-45的图像放大2倍的图像
3.2通过像素来实现图像的几何变换
先新建一个基类为CScrollView的单文档应用程序然后新添加一个图像处理的Cdibapi类,把一般处理图像时要用到的函数实现封装在这个类中,该类用于实现DIB对象的绘制,DIB对象调色板的创建,DIB对象的读取与存储,图像线性变换,图像灰度拉伸等。
然后为菜单栏添加一些新的菜单最后在视图类为新添加的菜单项添加消息处理函数
3.2.1图像的平移
有了上面的理论基础,可以十分容易的用Visual
C++来实现图像的平移。
在这里,只介绍灰度图像的平移,因为灰度图像每个像素位数正好是8位,即1个字节,这样,可以不必考虑拼凑字节的问题。
而且由于灰度图调色板的特殊性,处理时不必考虑调色板的问题。
根据上面的公式可以得到图像的平移程序流程图:
图3.1图像平移程序流程图
平移实现代码:
voidCImg_TransformView:
OnGeomTran()
CImg_TransformDoc*pDoc=GetDocument();
LPSTRlpDIB;
LPSTRlpDIBBits;
lpDIB=(LPSTR):
GlobalLock((HGLOBAL)pDoc->
GetHDIB());
if(:
DIBNumColors(lpDIB)!
=256)
MessageBox("
目前只支持256色位图的平移!
"
"
系统提示"
MB_ICONINFORMATION|MB_OK);
:
GlobalUnlock((HGLOBAL)pDoc->
return;
floatXOffset;
floatYOffset;
CTransDlgdlg;
dlg.m_Xoffset=10;
dlg.m_Yoffset=10;
if(dlg.DoModal()!
=IDOK)
{return;
}
XOffset=dlg.m_Xoffset;
YOffset=dlg.m_Yoffset;
deletedlg;
lpDIBBits=:
FindDIBBits(lpDIB);
if(TranslationDIB(lpDIBBits,:
DIBWidth(lpDIB),:
DIBHeight(lpDIB),XOffset,YOffset))
{
pDoc->
SetModifiedFlag(TRUE);
pDoc->
UpdateAllViews(NULL);
else
{MessageBox("
分配存失败!
MB_ICONINFORMATION|MB_OK);
:
平移实现结果:
平移前的图像水平平移50垂直平移50的图像
3.2.2图像的镜像
按照上面的变换公式,可以非常简单的实现图像的水平和垂直镜像操作。
下图是镜像操作的程序流程图:
镜像实现的代码:
OnGeomMirv()
目前只支持256色位图的镜像!
intbDirection;
CMirvDlgdlg;
{return;
bDirection=dlg.m_bDirection;
if(MirrorDIB(lpDIBBits,:
DIBHeight(lpDIB),bDirection))
GetHDIB())
镜像实验结果:
镜像前的图像水平镜像的图像
垂直镜像的图像
3.3图像的转置
图像转置的实现和图像镜像变换相似,不同之处在于图像转置后DIB的头
文件也要进行相应的改变,主要是将头文件中图像高度和宽度信息更新。
因此传递给图像转置函数的参数是直接指向DIB的指针,而不是直接指向DIB像素的指针。
根据公式可以得到如下所示的程序流程图:
图3.3图像转置的程序流程图
图像转置代码:
OnG