版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、面向?qū)ο蟪绦蛟O(shè)計(jì)學(xué) 號(hào):130085210002 學(xué)生所在學(xué)院:信息工程學(xué)院學(xué) 生 姓 名 :邵麗群任 課 教 師 :熊邦書教師所在學(xué)院:信息工程學(xué)院2013級(jí) 實(shí)現(xiàn)圖像的幾何變換電子信息工程信息工程學(xué)院摘要:幾何變換是最常見的圖像處理手段,通過(guò)對(duì)變形的圖像進(jìn)行幾何校正,可以得出準(zhǔn)確的圖像。常用的幾何變換功能包括圖像的平移、圖像的鏡像變換、圖像的轉(zhuǎn)置、圖像的縮放、圖像的旋轉(zhuǎn)等等。目前數(shù)字圖像處理的應(yīng)用越來(lái)越廣泛,已經(jīng)滲透到工業(yè)、航空航天、軍事等各個(gè)領(lǐng)域,在國(guó)民經(jīng)濟(jì)中發(fā)揮越來(lái)越大的作用。作為數(shù)字圖像處理的一個(gè)重要部分,本文接受的工作是如何Visual C+編程工具設(shè)計(jì)一個(gè)完整的應(yīng)用程序
2、,實(shí)現(xiàn)經(jīng)典的圖像幾何變換功能。程序大概分為兩大部分:讀寫B(tài)MP圖像,和數(shù)字圖像的幾何變換。即首先用Visual C+創(chuàng)建一個(gè)單文檔應(yīng)用程序框架,在實(shí)現(xiàn)任意BMP圖像的讀寫,打印,以及剪貼板操作的基礎(chǔ)上,完成經(jīng)典的圖像幾何變換功能。圖像幾何變換的Visual C+編程實(shí)現(xiàn),為校內(nèi)課題的實(shí)現(xiàn)提供了一個(gè)實(shí)例。 關(guān)鍵字:圖像處理;幾何變換(圖像的平移、縮放、轉(zhuǎn)置、旋轉(zhuǎn)和鏡像變換);BMP圖像;Visual C+一、引言圖像幾何變換是指用數(shù)學(xué)建模的方法來(lái)描述圖像位置、大小、形狀等變化的方法。在實(shí)際場(chǎng)景拍攝到的一幅圖像,如果畫面過(guò)大或過(guò)小,都需要進(jìn)行縮小
3、或放大。如果拍攝時(shí)景物與攝像頭不成相互平行關(guān)系的時(shí)候,會(huì)發(fā)生一些幾何畸變,例如會(huì)把一個(gè)正方形拍攝成一個(gè)梯形等。這就需要進(jìn)行一定的畸變校正。在進(jìn)行目標(biāo)物的匹配時(shí),需要對(duì)圖像進(jìn)行旋轉(zhuǎn)、平移等處理。在進(jìn)行三維景物顯示時(shí),需要進(jìn)行三維到二維平面的投影建模。因此,圖像幾何變換是圖像處理及分析的基礎(chǔ)。 圖像幾何變換是計(jì)算機(jī)圖像處理領(lǐng)域中的一個(gè)重要組成部分,也是值得深討的一個(gè)重要課題。在圖像幾何變換中主要包括圖像的放縮、圖像的旋轉(zhuǎn)、圖像的移動(dòng)、圖像的鏡像、圖像的塊操作等內(nèi)容,幾何變換不改變圖像的像素值,只改變像素所在的幾何位置。從廣義上說(shuō),圖像是自然界景物的客觀反映,是人類認(rèn)識(shí)世界和人類本身的重要
4、源泉。圖像對(duì)我們并不陌生。我們生活在一個(gè)信息時(shí)代,科學(xué)研究和統(tǒng)計(jì)表明,人類從外界獲得的信息約有75%來(lái)自視覺(jué)系統(tǒng),也就是從圖像中獲得的。所以對(duì)數(shù)字圖像的處理便顯得尤為重要了。本文主要深討了圖像的幾何變換(主要包括圖像的平移、轉(zhuǎn)置、縮放、旋轉(zhuǎn)、鏡像等)理論,并在此基礎(chǔ)上用Visual C+實(shí)現(xiàn)的過(guò)程。1.3.2研究方法方法一:利用 Windows 本身就提供了一個(gè)API函數(shù)SetWorldTransForm來(lái)實(shí)現(xiàn)圖片旋轉(zhuǎn)、位移及其他變形,這個(gè)函數(shù)是對(duì)一個(gè)設(shè)備上下文DC進(jìn)行操作,通過(guò)坐標(biāo)轉(zhuǎn)換來(lái)實(shí)現(xiàn)各種功能的。方法二:通過(guò)圖像進(jìn)行平移、旋轉(zhuǎn)、轉(zhuǎn)置、鏡像、縮放后重新計(jì)算各點(diǎn)新像素完成幾何變換。自定義一
5、個(gè)圖像處理的Cdibapi類,把一般處理圖像時(shí)要用到的函數(shù)實(shí)現(xiàn)封裝在這個(gè)類中,該類用于實(shí)現(xiàn)DIB對(duì)象的繪制,DIB對(duì)象調(diào)色板的創(chuàng)建,DIB對(duì)象的讀取與存儲(chǔ),圖像線性變換,圖像灰度拉伸等。然后把在視類中實(shí)現(xiàn)圖像平移,圖像鏡像,圖像轉(zhuǎn)置,圖像縮放及圖像旋轉(zhuǎn)的函數(shù)調(diào)用和實(shí)現(xiàn)。二、正文2.1灰度圖灰度圖(Grayscale)是指只含亮度信息,不含色彩信息的圖像。因此,要表示灰度圖,就需要把亮度值進(jìn)行量化。通常劃分為0到255共256個(gè)級(jí)別,0最暗(全黑),255最亮(全白)。BMP格式的文件中并沒(méi)有灰度圖這個(gè)概念,但是可以很容易的用BMP文件來(lái)表示灰度圖。方法是用256色的調(diào)色板,只不過(guò)這個(gè)調(diào)色板有點(diǎn)
6、特殊,每一項(xiàng)的RGB值都是相同的。也就是說(shuō)RGB值從(0,0,0),(1,1,1)一直到(255,255,255)。(0,0,0)是全黑色,(255,255,255)是全白色,中間的是灰色。2.2調(diào)色板調(diào)色板結(jié)構(gòu)LOGPALETTE,該結(jié)構(gòu)定義如下:typedef struct tagLOGPALETTE WORD palVersion;/調(diào)色板的板本號(hào),應(yīng)該指定該值為0x300;WORD palNumEntries;/調(diào)色板中的表項(xiàng)數(shù),對(duì)于灰度圖像該值為256; PALETEENTRY palPalEntry1;/調(diào)色板中的顏色表項(xiàng),由于該表項(xiàng)的數(shù) 目不一定,所以這里數(shù)組長(zhǎng)度定義為1,灰度圖
7、像對(duì)應(yīng)的該數(shù)組的長(zhǎng)度為256LOGPALETTE;顏色表項(xiàng)結(jié)構(gòu)PALETTEENTRY定義了調(diào)色板中的每一個(gè)顏色表項(xiàng)的顏色和使用方式,定義如下:typedef struct tagPALETTEENTRYBYTE peRed; /R分量值;BYTE peGreen; /G分量值;BYTE peBlue; /B分量值; BYTE peFlags; / 該顏色被使用的方式,一般情況下設(shè)為"0";PALETTEENTRY;Windows系統(tǒng)使用調(diào)色板管理器來(lái)管理與調(diào)色板有關(guān)的操作,通?;顒?dòng)窗口的調(diào)色板即是當(dāng)前系統(tǒng)調(diào)色板,所有的非活動(dòng)窗口都必須按照此系統(tǒng)調(diào)色板來(lái)顯示自己的顏色,此時(shí)
8、調(diào)色板管理器將自動(dòng)的用系統(tǒng)調(diào)色板中的最近似顏色來(lái)映射相應(yīng)的顯示顏色。如果窗口或應(yīng)用程序按自己的調(diào)色板顯示顏色,就必須將自己的調(diào)色板載入到系統(tǒng)調(diào)色板中,這種操作叫作實(shí)現(xiàn)調(diào)色板,實(shí)現(xiàn)調(diào)色板包括兩個(gè)步驟:1. 首先將調(diào)色板選擇到設(shè)備上下文中,可以通過(guò)CDC:SelectPalette() 選入設(shè)備上下文2. 然后在設(shè)備上下文中實(shí)現(xiàn)調(diào)色板,可以通過(guò) CDC:RealizePalette()實(shí)現(xiàn)設(shè)備調(diào)色板。1.2.4 BMP文件中DIB的結(jié)構(gòu)DIB是標(biāo)準(zhǔn)的Windows位圖格式,BMP文件中包含了一個(gè)DIB。一個(gè)BMP文件大體上分成如下4個(gè)部分:bfType=”BM”
9、bfSize bfReserved1 bfReserved2 bfOffBits BITMAPFILEHEADER 位圖文件頭 (只用于BMP文件) biSize biWidth biHeightbiPlanes biBitCount biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant BITMAPINFOHEADER 位圖信息頭 單色DIB有
10、2個(gè)表項(xiàng) 16色DIB有16個(gè)表項(xiàng)或更少256色DIB有256個(gè)表項(xiàng)或更少 真彩色DIB沒(méi)有調(diào)色板 每個(gè)表項(xiàng)長(zhǎng)度為4字節(jié)(32位)像素按照每行每列的順序排列 每一行的字節(jié)數(shù)必須是4的整數(shù) Palette調(diào)色板 DIB Pirxels DIB圖像數(shù)據(jù)2.3圖像的幾何變換基礎(chǔ)知識(shí)圖像的幾何變換,通常包括圖像的平移、圖像的鏡像變換、圖像的轉(zhuǎn)置、圖像的縮放和圖像的旋轉(zhuǎn)等。程序結(jié)束圖像的縮放圖像的轉(zhuǎn)置圖像的鏡像圖像的平移程序開始讀寫B(tài)MP圖像圖像的旋轉(zhuǎn)圖2.1 程序基本框架圖2.3.1圖像的平移圖像的平移是幾何變換中最簡(jiǎn)單的變換之一。圖像平
11、移就是將圖像中所有的點(diǎn)都按照指定的平移量水平、垂直移動(dòng)。設(shè)(x0,y0)坐標(biāo)將變?yōu)椋▁1,y1)。顯然(x0,y0)和(x1,y1)的關(guān)系如下:x1=x0+txy1=y0+ty用矩陣表示如下:x1y11=1 0 tx0 1 ty0 0 1x0y01對(duì)該矩陣求逆,可以得到逆變換:x0y01=1 0 -tx0 1 -ty0 0 1x1y11即x0=x1-txy0=y1-ty這樣,平移后的圖像上的每一點(diǎn)都可以在原圖像中找到對(duì)應(yīng)的點(diǎn)。例如,對(duì)于新圖中的(0,0)像素,代入上面的方程組,可以求出對(duì)應(yīng)原圖中的像素(-tx,-ty)。如果tx或ty大于0,則(-tx,-ty)不在原圖中。對(duì)于不在原圖中的點(diǎn),
12、可以直接將它的像素值統(tǒng)一設(shè)置為0或則255(對(duì)于灰度圖就是黑色或白色)。同樣,若有點(diǎn)不在原圖中,也就說(shuō)明原圖中有點(diǎn)被移出顯示區(qū)域。如果不想丟失被移出的部分圖像,可以將新生成的圖像寬度擴(kuò)大|tx|,高度擴(kuò)大|ty|。2.3.2圖像的鏡像圖像的鏡像變換分為兩種:一種是水平鏡像,另外一種是垂直鏡像。圖像的水平鏡像操作是將圖像的左半部分和右半部分以圖像垂直中軸線為中心鏡像進(jìn)行對(duì)換;圖像的垂直鏡像操作是將圖像上半部分和下半部分以圖像水平中軸線為中心鏡像進(jìn)行對(duì)換。設(shè)圖像高度為lHeight,寬度為lWidth,原圖中(x0,y0)經(jīng)過(guò)水平鏡像后坐標(biāo)將變?yōu)椋╨Width-x0,y0),其矩陣表達(dá)式為:x1y
13、11=-1 0 lWidth0 1 ty0 0 1x0y01逆運(yùn)算表達(dá)式為:x0y01=-1 0 lWidth0 1 00 0 1x1y11即同樣,(x0,y0)經(jīng)過(guò)垂直鏡像后坐標(biāo)將變?yōu)椋▁0,lHeight-y0),其矩陣表達(dá)式為:x1y11=1 0 0 0 -1 lHeight 0 0 1 x0y01逆運(yùn)算矩陣表達(dá)式為:x0y01=1 0 0 0 -1 lHeight 0 0 1 x1y11 即x0=x1y0=lHeight-y12.3.3圖像的轉(zhuǎn)置圖像的轉(zhuǎn)置操作是將圖像像素的x坐標(biāo)和y坐標(biāo)互換。該操作將改變圖像的大小,圖像的高度和寬度將互換。轉(zhuǎn)置表達(dá)式:x1y11=1 0 tx0 1 t
14、y0 0 1x0y01它的逆矩陣表達(dá)式:x0y01=1 0 tx0 1 ty0 0 1x1y11 即x0=x1y0=y12.3.4圖像的縮放上面的幾種圖像幾何變換中都是1:1的變換,而圖像的縮放操作將會(huì)改變圖像的大小,產(chǎn)生的圖像中的像素可能在原圖中找不到相應(yīng)的像素點(diǎn),這樣就必須進(jìn)行近似處理。一般的方法是直接賦值為和它最相近的像素值,也可以通過(guò)一些插值算法來(lái)計(jì)算。下面的代碼直接采用了前一種做法。假設(shè)圖像x軸方向縮放比率為fx,y軸方向縮放比率為fy,那么原圖中點(diǎn)(x0,y0)對(duì)應(yīng)與新圖中的點(diǎn)(x1,y1)的轉(zhuǎn)換矩陣為:x1y11=fx 0 00 fy 00 0 1x0y01其逆運(yùn)算如下:x0y0
15、1=1/fx 0 0 0 1/fy 0 0 0 1x1y11 即x0=x1/fxy0=y1/fy例如,當(dāng)fx=fy=0.5時(shí),圖像被縮放到一半大小,此時(shí)縮小后圖像中的(0,0)像素對(duì)應(yīng)于原圖中的(0,0)像素;(0,1)像素對(duì)應(yīng)于原圖中的(0,2)像素;(1,0)像素對(duì)應(yīng)于原圖中的(2,0)像素,以此類推。在原圖基礎(chǔ)上,每行隔一個(gè)像素取一點(diǎn),每隔一行進(jìn)行操作。其實(shí)是將原圖每行中的像素重復(fù)取值一遍,然后每行重復(fù)一次。2.3.5圖像的旋轉(zhuǎn)一般圖像的旋轉(zhuǎn)是以圖像的中心為原點(diǎn),旋轉(zhuǎn)一定的角度。旋轉(zhuǎn)后,圖像的大小一般會(huì)改變。和圖像平移一樣,既可以把轉(zhuǎn)出顯示區(qū)域的圖像截去,也可以擴(kuò)大圖像范圍以顯示所有的圖
16、像。可以推導(dǎo)一下旋轉(zhuǎn)運(yùn)算的變換公式。如下圖所示,點(diǎn)(x0,y0)經(jīng)過(guò)旋轉(zhuǎn)度后坐標(biāo)變成(x1,y1)。在旋轉(zhuǎn)前:x0=cos()y0=sin()轉(zhuǎn)置后:x1=cos-=cos()cos()+sin()sin()=x0cos()+y0sin()y1=sin-=sincos-cossin=-x0sin()+y0cos()寫成矩陣表達(dá)式為:x1y11= cos sin() 0-sin cos() 0 0 0 1x0y01其逆運(yùn)算如下:x0y01= cos -sin() 0sin cos() 0 0 0 1x1y11有了上面的轉(zhuǎn)換公式,就可以非常方便的編寫出實(shí)現(xiàn)圖像旋轉(zhuǎn)的函數(shù)。首先應(yīng)計(jì)算出公式中需要的幾
17、個(gè)參數(shù):a,b,c,d和旋轉(zhuǎn)后新圖像的高、寬度?,F(xiàn)在已知圖像的原始寬度為lWidth,高度為lHeight,以圖像中心為坐標(biāo)系原點(diǎn),則原始圖像四個(gè)角的坐標(biāo)分別為-lWidth-12,lHeight-12, lWidth-12,lHeight-12, lWidth-12,-lHeight-12和 -lWidth-12,-lHeight-12,按照旋轉(zhuǎn)公式,在旋轉(zhuǎn)后的新圖中,這四個(gè)點(diǎn)坐標(biāo)為:fDstX1,fDstY1=-lWidth-12cos+lHeight-12sin,lWidth-12sin()+lHeight-12cos()fDstX2,fDstY2=lWidth-12cos+lHeigh
18、t-12sin,-lWidth-12sin()+lHeight-12cos()fDstX1,fDstY1=lWidth-12cos-lHeight-12sin,-lWidth-12sin-lHeight-12cos()fDstX1,fDstY1=-lWidth-12cos-lHeight-12sin,lWidth-12sin-lHeight-12cos()則新圖像的寬度lNewWidth和高度lNewHeight為:lNewWidth=maxfDstX4-fDstX1,fDstX3-fDstX2lNewHeight=maxfDstY4-fDstY1,fDstY3-fDstY2令f1=-ccos
19、-dsin+af2=csin-dcos+b,其中a=lWidth-12, b=lHeight-12, c=lNewWidth-12, b=lNewHeight-12,則x0=x1cos+y1sin+f1y0=-x1sin+y1cos+f22.4 Visual C+簡(jiǎn)述VisualC+是微軟公司提供的基于C/C+的應(yīng)用程序集成開發(fā)工具。VC擁有豐富的功能和大量的擴(kuò)展庫(kù),使用它能有效的創(chuàng)建高性能的Windows應(yīng)用程序和Web應(yīng)用程序。VC的優(yōu)越性主要表現(xiàn)在以下幾個(gè)方面:開發(fā)分布式應(yīng)用、開發(fā)的應(yīng)用程序運(yùn)行效率高、具有健壯性、能縮短軟件升級(jí)周期。能夠生成多線程應(yīng)用,而多線程應(yīng)用對(duì)于增加并發(fā)
20、響應(yīng)有實(shí)際意義。VC除了提供高效的C/C+編譯器外,還提供了大量的可重用類和組件,包括著名的微軟基礎(chǔ)類庫(kù)(MFC)和活動(dòng)模板類庫(kù)(ATL),因此它是軟件開發(fā)人員不可多得的開發(fā)工具。將Visual C+應(yīng)用于數(shù)字圖像的幾何變換,VC豐富的功能和大量的擴(kuò)展庫(kù),類的重用特性以及它對(duì)函數(shù)庫(kù)、DLL庫(kù)的支持能使程序更好的模塊化,并且通過(guò)向?qū)С绦虼蟠蠛?jiǎn)化了庫(kù)資源的使用和應(yīng)用程序的開發(fā),正由于VC具有明顯的優(yōu)勢(shì),因而我選擇了它來(lái)作為數(shù)字圖像幾何變換的開發(fā)工具。在本程序的開發(fā)過(guò)程中,VC的核心知識(shí)、消息映射機(jī)制、對(duì)話框控件編程等都得到了生動(dòng)的體現(xiàn)和靈活的應(yīng)用。三、實(shí)驗(yàn)步驟及結(jié)果3.1 通過(guò)API函數(shù)
21、SetWorldTransForm實(shí)現(xiàn)圖像幾何變換API函數(shù)SetWorldTransForm實(shí)現(xiàn)圖像幾何變換使用XFORM來(lái)控制DC時(shí),需要先設(shè)置繪圖模式SetGraphicsMode為GM_ADVANCED,再用SetWorldTransform。否則SetWorldTransform函數(shù)會(huì)失敗。setWorldTransForm內(nèi)部的算法其實(shí)相當(dāng)于用線性代數(shù)里矩陣與一個(gè)向量相乘的辦法來(lái)解決圖形的變換,只要我們知道要乘上的變換方程是哪一個(gè),就能進(jìn)行各種變換(不止是旋轉(zhuǎn)), 這個(gè)函數(shù)是對(duì)一個(gè)設(shè)備上下文DC進(jìn)行操作,通過(guò)坐標(biāo)轉(zhuǎn)換來(lái)實(shí)現(xiàn)各種功能的。函數(shù)原型:int SetGraphicsMode
22、(HDC hdc, int iMode);參數(shù):hdc:指向設(shè)備環(huán)境的句柄。 iMode:指定圖形模式,該參數(shù)取值參看MSDN函數(shù)原型:BOOL SetWorldTransform(HDC hdc, CONST XFORM *lpXform);參數(shù):hdc:指向設(shè)備環(huán)境的句柄。 lpxform:指向XFORM結(jié)構(gòu)的指針,此結(jié)構(gòu)含有轉(zhuǎn)換數(shù)據(jù)。返回值:如果函數(shù)調(diào)用成功,返回值為非零值,否則為零。編程原理:對(duì)于選定DC的任何坐標(biāo)(x, y)將被SetWindowsForm設(shè)定的變換轉(zhuǎn)換為坐標(biāo)(x, y),兩個(gè)坐標(biāo)的對(duì)應(yīng)關(guān)系是: x = x * eM11
23、0;+ y * eM12 + eDx;y = x * eM12 + y * eM22 + eDy;對(duì)于一個(gè)轉(zhuǎn)換的操作,數(shù)學(xué)上的轉(zhuǎn)換方式是:x2 = cos(q)*(x1-x0) sin(q)*(y1-y0) + x0;y2 = sin(q)*(x1-x0) + cos(q)*(y1-y0) + y0;于是,我們可以得到SetW
24、orldTransForm的一組參數(shù):xform.eM11 = cos(q);xform.eM12 = sin(q);xform.eM21 = -sin(q);xform.eM22 = cos(q); xform.eDx = x0-cos(q)*x0+sin(q)*y0; xform.eDy = y0-cos(q)*y0-sin(q)*x0;實(shí)驗(yàn)步驟:一、先新建一個(gè)對(duì)話框的應(yīng)用程序; 二、修改對(duì)話框的屬性將其Caption屬性改為“圖片處理”,Border屬性改為“Resiz
25、ing”,為其添加一些控件并未其中的而一些控件關(guān)聯(lián)變量且修改控件的屬性如圖:三、為旋轉(zhuǎn)、縮放、平移控件添加消息處理及繪制矩形和橢圓、旋轉(zhuǎn)DC等代碼3.1.1圖像旋轉(zhuǎn)的代碼及結(jié)果: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 = (f
26、loat)(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); 實(shí)驗(yàn)結(jié)果:旋轉(zhuǎn)前圖像 旋轉(zhuǎn)23°的圖像 旋轉(zhuǎn)123°的圖像 旋轉(zhuǎn)312°的圖像3.1.2圖像縮放的代碼及結(jié)果試驗(yàn)代碼:if ( m_iSize != 1 ) fangle = (double)m
27、_iAngle / 180. * 3.1415926; 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);
28、xform.eDy = (float)(centerPt.y - m_iSize*cos(fangle)*centerPt.y - m_iSize*sin(fangle)*centerPt.x+m_iPanRight); SetWorldTransform(hDc, &xform); 實(shí)驗(yàn)結(jié)果: 縮放前的圖像 放大2.5倍的圖像縮小0.5倍的圖像 放大2.5倍且旋轉(zhuǎn)50°的圖像3.1.3圖像平移的代碼及結(jié)果實(shí)驗(yàn)代碼:if ( m_iPanLeft != 0|m_iPanRight!=0 ) fangle = (double)m_iAngle / 180. * 3.141592
29、6; 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+m_iPanLeft); xform.eDy = (float)(centerPt.y - cos(fangle)*centerPt.y - sin(fangle)*cen
30、terPt.x+m_iPanRight); SetWorldTransform(hDc, &xform); 實(shí)驗(yàn)結(jié)果:平移前的圖像 橫向平移56.5縱向平移45的圖像橫向平移56縱向平移45且旋轉(zhuǎn)45° 橫向平移-56縱向平移-45的圖像 放大2倍的圖像3.2通過(guò)像素來(lái)實(shí)現(xiàn)圖像的幾何變換實(shí)驗(yàn)步驟:先新建一個(gè)基類為CScrollView的單文檔應(yīng)用程序然后新添加一個(gè)圖像處理的Cdibapi類,把一般處理圖像時(shí)要用到的函數(shù)實(shí)現(xiàn)封裝在這個(gè)類中,該類用于實(shí)現(xiàn)DIB對(duì)象的繪制,DIB對(duì)象調(diào)色板的創(chuàng)建,DIB對(duì)象的讀取與存儲(chǔ),圖像線性變換,圖像灰度拉伸等。然后為菜單欄添加一些新的菜單最后
31、在視圖類為新添加的菜單項(xiàng)添加消息處理函數(shù)3.2.1圖像的平移有了上面的理論基礎(chǔ),可以十分容易的用Visual C+來(lái)實(shí)現(xiàn)圖像的平移。在這里,只介紹灰度圖像的平移,因?yàn)榛叶葓D像每個(gè)像素位數(shù)正好是8位,即1個(gè)字節(jié),這樣,可以不必考慮拼湊字節(jié)的問(wèn)題。而且由于灰度圖調(diào)色板的特殊性,處理時(shí)不必考慮調(diào)色板的問(wèn)題。根據(jù)上面的公式可以得到圖像的平移程序流程圖:程序開始單擊“文件”->“打開”打開一幅圖像單擊“幾何變換”->圖像平移獲取水平平移量和垂直平移量 計(jì)算指向新DIB第i行,第j個(gè)像素的指針提示用戶將該像素賦值為255 程序結(jié)束是 程序結(jié)束設(shè)置臟標(biāo)記
32、更新視圖復(fù)制平移后的圖像直接復(fù)制像素判斷平移是否成功計(jì)算指向原DIB在該坐標(biāo)下像素的指針計(jì)算該像素在原DIB中的坐標(biāo)判斷坐標(biāo)是否在原圖范圍內(nèi)否否 圖3.1圖像平移程序流程圖平移實(shí)現(xiàn)代碼:void CImg_TransformView:OnGeomTran() CImg_TransformDoc* pDoc = GetDocument();LPSTRlpDIB; LPSTR lpDIBBits;lpDIB = (LPSTR) :GlobalLock(HGLOBAL) pDoc->GetHDIB();if (:DIBNumColors(lpDIB) != 256)MessageBox(&qu
33、ot;目前只支持256色位圖的平移!", "系統(tǒng)提示" , MB_ICONINFORMATION |MB_OK);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB();return;float XOffset; float YOffset;CTransDlg dlg;dlg.m_Xoffset=10; dlg.m_Yoffset=10; if(dlg.DoModal ()!=IDOK)return ;XOffset=dlg.m_Xoffset ;YOffset=dlg.m_Yoffset ;delete dlg;lpDIBBits=:
34、FindDIBBits(lpDIB);if (TranslationDIB(lpDIBBits, :DIBWidth(lpDIB), :DIBHeight(lpDIB), XOffset, YOffset) pDoc->SetModifiedFlag(TRUE); pDoc->UpdateAllViews(NULL);elseMessageBox("分配內(nèi)存失??!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB();平移實(shí)現(xiàn)結(jié)果:平移
35、前的圖像 水平平移50垂直平移50的圖像 3.2.2圖像的鏡像圖像的鏡像變換分為兩種:一種是水平鏡像,另外一種是垂直鏡像。圖像的水平鏡像操作是將圖像的左半部分和右半部分以圖像垂直中軸線為中心鏡像進(jìn)行對(duì)換;圖像的垂直鏡像操作是將圖像上半部分和下半部分以圖像水平中軸線為中心鏡像進(jìn)行對(duì)換。按照上面的變換公式,可以非常簡(jiǎn)單的實(shí)現(xiàn)圖像的水平和垂直鏡像操作。下圖是鏡像操作的程序流程圖:程序開始單擊“文件”->“打開”打開一幅圖像否是否水平鏡像針對(duì)每行圖像左半部分進(jìn)行操作針對(duì)上半圖像進(jìn)行操作操作 計(jì)算指向倒數(shù)第i行像素起點(diǎn)的指針計(jì)算指向倒數(shù)第i行,第j個(gè)像素的指針計(jì)算指向第i行像素起點(diǎn)的指針計(jì)算指向倒
36、數(shù)第i行,倒數(shù)第j個(gè)像素的指針備份一行備份一個(gè)像素將倒數(shù)第i行像素復(fù)制到第i行將倒數(shù)第i行,第j個(gè)像素復(fù)制到倒數(shù)第i行,倒數(shù)第j個(gè)像素將倒數(shù)第i行,倒數(shù)第j個(gè)像素復(fù)制到倒數(shù)第i行,第j個(gè)像素將第i行像素復(fù)制到倒數(shù)第i行 否提示用戶 程序結(jié)束是 程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷鏡像是否成功鏡像實(shí)現(xiàn)的代碼:void CImg_TransformView:OnGeomMirv() CImg_TransformDoc* pDoc = GetDocument();LPSTRlpDIB; LPSTR lpDIBBits;lpDIB = (LPSTR) :GlobalLock(HGLOBA
37、L) pDoc->GetHDIB();if (:DIBNumColors(lpDIB) != 256)MessageBox("目前只支持256色位圖的鏡像!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB();return;int bDirection;CMirvDlg dlg; if(dlg.DoModal ()!=IDOK)return ;bDirection=dlg.m_bDirection ;delete dlg;lpDIBBits
38、=:FindDIBBits(lpDIB);if(MirrorDIB(lpDIBBits,:DIBWidth(lpDIB), :DIBHeight(lpDIB),bDirection)pDoc->SetModifiedFlag(TRUE);pDoc->UpdateAllViews(NULL);elseMessageBox("分配內(nèi)存失敗!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB()鏡像實(shí)驗(yàn)結(jié)果: 鏡像前的圖像 水平鏡像的圖像 垂
39、直鏡像的圖像3.3圖像的轉(zhuǎn)置圖像轉(zhuǎn)置的實(shí)現(xiàn)和圖像鏡像變換相似,不同之處在于圖像轉(zhuǎn)置后DIB的頭文件也要進(jìn)行相應(yīng)的改變,主要是將頭文件中圖像高度和寬度信息更新。因此傳遞給圖像轉(zhuǎn)置函數(shù)的參數(shù)是直接指向DIB的指針,而不是直接指向DIB像素的指針。根據(jù)公式可以得到如下所示的程序流程圖:程序開始單擊“文件”->“打開”打開一幅圖像單擊“幾何變換”->圖像轉(zhuǎn)置針對(duì)每行圖像每列進(jìn)行操作 計(jì)算指向原DIB第i行,第j個(gè)像素的指針計(jì)算指向轉(zhuǎn)置DIB第j行,第i個(gè)像素的指針復(fù)制轉(zhuǎn)置后的圖像復(fù)制像素互換DIB中圖像的高寬否提示用戶 程序結(jié)束是 程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否
40、成功 圖3.3 圖像轉(zhuǎn)置的程序流程圖圖像轉(zhuǎn)置代碼:void CImg_TransformView:OnGeomTrpo()CImg_TransformDoc* pDoc = GetDocument();LPSTRlpDIB;LPSTR lpDIBBits;lpDIB = (LPSTR) :GlobalLock(HGLOBAL) pDoc->GetHDIB();if (:DIBNumColors(lpDIB) != 256)MessageBox("目前只支持256色位圖的轉(zhuǎn)置!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_O
41、K);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB();return;if(TransposeDIB(lpDIB)pDoc->SetModifiedFlag(TRUE);pDoc->UpdateAllViews(NULL);elseMessageBox("分配內(nèi)存失敗!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);轉(zhuǎn)置實(shí)驗(yàn)結(jié)果:轉(zhuǎn)置前的圖像 轉(zhuǎn)置后的圖像3.2.4圖像的縮放上面的幾種圖像幾何變換中都是1:1的變換,而圖像的縮放操作將會(huì)改變圖像的大小,產(chǎn)生的圖像中的像素可能在原
42、圖中找不到相應(yīng)的像素點(diǎn),這樣就必須進(jìn)行近似處理。一般的方法是直接賦值為和它最相近的像素值,也可以通過(guò)一些插值算法來(lái)計(jì)算。下面的代碼直接采用了前一種做法。按照上面的轉(zhuǎn)換公式,可以容易的寫出圖像的縮放程序流程圖:程序開始 單擊“文件”->“打開”打開一幅圖像單擊“幾何變換”->圖像縮放獲取水平縮放量和垂直縮放量 更新DIB中圖像的高度和寬度針對(duì)圖像每行每列進(jìn)行操作計(jì)算指向原DIB第i行,第j個(gè)像素的指針計(jì)算指向轉(zhuǎn)置DIB第j行,第i個(gè)像素的指針復(fù)制轉(zhuǎn)置后的圖像復(fù)制像素互換DIB中圖像的高寬否提示用戶 程序結(jié)束是 程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功 3.4圖像
43、縮放的程序流程圖圖像縮放代碼:void CImg_TransformView:OnGeomZoom()CImg_TransformDoc* pDoc = GetDocument();LPSTR lpDIB;lpDIB = (LPSTR) :GlobalLock(HGLOBAL) pDoc->GetHDIB();if (:DIBNumColors(lpDIB) != 256)MessageBox("目前只支持256色位圖的縮放!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnlock(HGLOBAL)
44、 pDoc->GetHDIB();return;float fXZoomRatio;float fYZoomRatio;CZoomDlg dlg;dlg.m_XZoom=0.5;dlg.m_YZoom=0.5; if(dlg.DoModal ()!=IDOK)return ;fXZoomRatio=dlg.m_XZoom ; fYZoomRatio=dlg.m_YZoom ;delete dlg;HDIB hNewDIB = NULL;hNewDIB = (HDIB) ZoomDIB(lpDIB, fXZoomRatio, fYZoomRatio);if (hNewDIB != NULL
45、)pDoc->ReplaceHDIB(hNewDIB);pDoc->InitDIBData();pDoc->SetModifiedFlag(TRUE); SetScrollSizes(MM_TEXT, pDoc->GetDocSize();pDoc->UpdateAllViews(NULL);else MessageBox("分配內(nèi)存失??!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB();縮放實(shí)驗(yàn)結(jié)果:縮放前的圖
46、像 水平和垂直都縮小0.5倍的圖像水平和垂直都放大1.5倍的圖像3.2.5圖像的旋轉(zhuǎn)一般圖像的旋轉(zhuǎn)是以圖像的中心為原點(diǎn),旋轉(zhuǎn)一定的角度。旋轉(zhuǎn)后,圖像的大小一般會(huì)改變。和圖像平移一樣,既可以把轉(zhuǎn)出顯示區(qū)域的圖像截去,也可以擴(kuò)大圖像范圍以顯示所有的圖像,程序流程圖如下:程序開始單擊“文件”->“打開”打開一幅圖像單擊“幾何變換”->圖像旋轉(zhuǎn)獲取旋轉(zhuǎn)角度計(jì)算旋轉(zhuǎn)角度的正弦和余弦 計(jì)算原圖和新圖四個(gè)角的坐標(biāo) 否提示用戶 程序結(jié)束是 程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功計(jì)算旋轉(zhuǎn)后圖像實(shí)際寬度和高度針對(duì)圖像每行每列進(jìn)行操作計(jì)算指向新DIB第i行,第j個(gè)像素的
47、指針計(jì)算該像素在原DIB中的坐標(biāo)否否提示用戶將該像素賦值為255 程序結(jié)束是 程序結(jié)束設(shè)置臟標(biāo)記更新視圖復(fù)制平移后的圖像直接復(fù)制像素判斷平移是否成功計(jì)算指向原DIB在該坐標(biāo)下像素的指針判斷坐標(biāo)是否在原圖范圍內(nèi)圖3.5 圖像旋轉(zhuǎn)的程序流程圖圖像旋轉(zhuǎn)代碼:void CImg_TransformView:OnGeomRota() CImg_TransformDoc* pDoc = GetDocument();LPSTR lpDIB;lpDIB = (LPSTR) :GlobalLock(HGLOBAL) pDoc->GetHDIB();MessageBox(&q
48、uot;目前只支持256色位圖的縮放!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnlock(HGLOBAL) pDoc->GetHDIB();return;float iRotateAngle;CRotateDlg dlg;dlg.m_iRotateAngle=90; if(dlg.DoModal ()!=IDOK)return ;iRotateAngle=dlg.m_iRotateAngle ;delete dlg;HDIB hNewDIB = NULL;hNewDIB = (HDIB)RotateDI
49、B(lpDIB, iRotateAngle);if (hNewDIB != NULL) pDoc->ReplaceHDIB(hNewDIB);pDoc->InitDIBData();pDoc->SetModifiedFlag(TRUE); SetScrollSizes(MM_TEXT, pDoc->GetDocSize();pDoc->UpdateAllViews(NULL);elseMessageBox("分配內(nèi)存失??!", "系統(tǒng)提示" , MB_ICONINFORMATION | MB_OK);:GlobalUnloc
50、k(HGLOBAL) pDoc->GetHDIB();旋轉(zhuǎn)實(shí)驗(yàn)結(jié)果:旋轉(zhuǎn)前圖像 旋轉(zhuǎn)65°的圖像四、結(jié)論與體會(huì)本例只針對(duì)256級(jí)灰度圖進(jìn)行處理。由于本程序首先要實(shí)現(xiàn)任意BMP圖像的讀寫,打印,以及剪貼板操作,故用Visual C+創(chuàng)建一個(gè)單文檔應(yīng)用程序框架,然后根據(jù)BMP圖像的結(jié)構(gòu)定義自己的函數(shù)庫(kù),函數(shù)庫(kù)中包括經(jīng)常要用到的功能,例如創(chuàng)建DIB對(duì)象調(diào)色板,返回DIB寬度和高度等,這樣在要使用DIB時(shí),只需要對(duì)它進(jìn)行調(diào)用就可以了。最后,在對(duì)BMP圖像各種基礎(chǔ)操作實(shí)現(xiàn)的基礎(chǔ)上,完成經(jīng)典的圖像幾何變換功能。包括:1 圖像的平移。經(jīng)典的圖像平移有兩種算法,一種不會(huì)改變圖像大小,另一種可以相應(yīng)擴(kuò)大圖像。本程序采用了第一種算法。為了使圖像能按照用戶指定的水平平移量和垂直平移量移動(dòng),作者首先定義了一個(gè)參數(shù)設(shè)定窗,并在圖像平移菜單的事件處理函數(shù)中對(duì)此對(duì)話框進(jìn)行定義,獲取平移量。然后調(diào)用圖像平移函數(shù),從而實(shí)現(xiàn)將圖像中所有的點(diǎn)(像素)都按照指定的平移量水平、垂直移動(dòng),平移后的圖像上的每一點(diǎn)都可以在原圖像中找到對(duì)應(yīng)的點(diǎn)。2 圖像的鏡像。圖像的水平鏡像操作是將圖像的左半部分和右半部分以圖像垂直中軸線為中心鏡像進(jìn)行對(duì)換;圖像的垂直鏡像操作是將圖像上半部分和下半部分以圖像
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 個(gè)人城鎮(zhèn)建房合同范例
- 外貿(mào)采礦合同模板
- 建筑施工合同范例簡(jiǎn)易
- 南川無(wú)船承運(yùn)業(yè)務(wù)合同范例
- 墻面油漆合同范例
- 樂(lè)山專業(yè)保安合同范例
- 養(yǎng)殖人員合同范例
- 養(yǎng)生按摩勞務(wù)合同范例
- 書本合同范例
- 葉縣生豬購(gòu)銷合同模板
- 車身噴漆部件用量參考標(biāo)準(zhǔn)表
- 食品安全管理員任命書范文
- 完整版中華醫(yī)學(xué)會(huì)瘧疾診療規(guī)范
- 北師大版七年級(jí)生物上冊(cè)教案(全冊(cè)完整版)
- 防腐油漆施工工藝
- 南方S82T操作手冊(cè)
- 設(shè)備采購(gòu)安裝工程結(jié)算書
- [精品]臺(tái)灣地區(qū)零售藥店的現(xiàn)狀與發(fā)展趨勢(shì)
- 焙燒爐煙氣換熱器的設(shè)計(jì)方案
- 血漿置換及臨床的應(yīng)用業(yè)內(nèi)特制
- 雨蝶(李翊君)原版正譜鋼琴譜五線譜樂(lè)譜.docx
評(píng)論
0/150
提交評(píng)論