圖像的幾何變換的兩種實(shí)現(xiàn)(旋轉(zhuǎn)、平移、放大、縮小)_第1頁
圖像的幾何變換的兩種實(shí)現(xiàn)(旋轉(zhuǎn)、平移、放大、縮小)_第2頁
圖像的幾何變換的兩種實(shí)現(xiàn)(旋轉(zhuǎn)、平移、放大、縮小)_第3頁
圖像的幾何變換的兩種實(shí)現(xiàn)(旋轉(zhuǎn)、平移、放大、縮小)_第4頁
圖像的幾何變換的兩種實(shí)現(xiàn)(旋轉(zhuǎn)、平移、放大、縮小)_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

面向?qū)ο蟪绦蛟O(shè)計(jì)學(xué)號(hào):130085210002學(xué)生所在學(xué)院:信息工程學(xué)院學(xué)生姓名:邵麗群任課教師:熊邦書教師所在學(xué)院:信息工程學(xué)院2013級(jí)實(shí)現(xiàn)圖像的幾何變換電子信息工程信息工程學(xué)院摘要:幾何變換是最常見的圖像處理手段,通過對(duì)變形的圖像進(jìn)行幾何校正,可以得出準(zhǔn)確的圖像。常用的幾何變換功能包括圖像的平移、圖像的鏡像變換、圖像的轉(zhuǎn)置、圖像的縮放、圖像的旋轉(zhuǎn)等等。目前數(shù)字圖像處理的應(yīng)用越來越廣泛,已經(jīng)滲透到工業(yè)、航空航天、軍事等各個(gè)領(lǐng)域,在國(guó)民經(jīng)濟(jì)中發(fā)揮越來越大的作用。作為數(shù)字圖像處理的一個(gè)重要部分,本文接受的工作是如何Visual

C++編程工具設(shè)計(jì)一個(gè)完整的應(yīng)用程序,實(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é)建模的方法來描述圖像位置、大小、形狀等變化的方法。在實(shí)際場(chǎng)景拍攝到的一幅圖像,如果畫面過大或過小,都需要進(jìn)行縮小或放大。如果拍攝時(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)容,幾何變換不改變圖像的像素值,只改變像素所在的幾何位置。從廣義上說,圖像是自然界景物的客觀反映,是人類認(rèn)識(shí)世界和人類本身的重要源泉。圖像對(duì)我們并不陌生。我們生活在一個(gè)信息時(shí)代,科學(xué)研究和統(tǒng)計(jì)表明,人類從外界獲得的信息約有75%來自視覺系統(tǒng),也就是從圖像中獲得的。所以對(duì)數(shù)字圖像的處理便顯得尤為重要了。本文主要深討了圖像的幾何變換(主要包括圖像的平移、轉(zhuǎn)置、縮放、旋轉(zhuǎn)、鏡像等)理論,并在此基礎(chǔ)上用VisualC++實(shí)現(xiàn)的過程。1.3.2研究方法方法一:利用Windows本身就提供了一個(gè)API函數(shù)SetWorldTransForm來實(shí)現(xiàn)圖片旋轉(zhuǎn)、位移及其他變形,這個(gè)函數(shù)是對(duì)一個(gè)設(shè)備上下文DC進(jìn)行操作,通過坐標(biāo)轉(zhuǎn)換來實(shí)現(xiàn)各種功能的。方法二:通過圖像進(jìn)行平移、旋轉(zhuǎn)、轉(zhuǎn)置、鏡像、縮放后重新計(jì)算各點(diǎn)新像素完成幾何變換。自定義一個(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格式的文件中并沒有灰度圖這個(gè)概念,但是可以很容易的用BMP文件來表示灰度圖。方法是用256色的調(diào)色板,只不過這個(gè)調(diào)色板有點(diǎn)特殊,每一項(xiàng)的RGB值都是相同的。也就是說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)定義如下:typedefstructtagLOGPALETTE

{

WORDpalVersion;//調(diào)色板的板本號(hào),應(yīng)該指定該值為0x300;

WORDpalNumEntries;//調(diào)色板中的表項(xiàng)數(shù),對(duì)于灰度圖像該值為256;

PALETEENTRYpalPalEntry[1];//調(diào)色板中的顏色表項(xiàng),由于該表項(xiàng)的數(shù)目不一定,所以這里數(shù)組長(zhǎng)度定義為1,灰度圖像對(duì)應(yīng)的該數(shù)組的長(zhǎng)度為256}LOGPALETTE;顏色表項(xiàng)結(jié)構(gòu)PALETTEENTRY定義了調(diào)色板中的每一個(gè)顏色表項(xiàng)的顏色和使用方式,定義如下:

typedefstructtagPALETTEENTRY

{

BYTEpeRed;//R分量值;

BYTEpeGreen;//G分量值;

BYTEpeBlue;//B分量值;

BYTEpeFlags;//該顏色被使用的方式,一般情況下設(shè)為"0";

}PALETTEENTRY;Windows系統(tǒng)使用調(diào)色板管理器來管理與調(diào)色板有關(guān)的操作,通?;顒?dòng)窗口的調(diào)色板即是當(dāng)前系統(tǒng)調(diào)色板,所有的非活動(dòng)窗口都必須按照此系統(tǒng)調(diào)色板來顯示自己的顏色,此時(shí)調(diào)色板管理器將自動(dòng)的用系統(tǒng)調(diào)色板中的最近似顏色來映射相應(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è)備上下文中,可以通過CDC::SelectPalette()選入設(shè)備上下文2.

然后在設(shè)備上下文中實(shí)現(xiàn)調(diào)色板,可以通過CDC::RealizePalette()實(shí)現(xiàn)設(shè)備調(diào)色板。1.2.4BMP文件中DIB的結(jié)構(gòu)DIB是標(biāo)準(zhǔn)的Windows位圖格式,BMP文件中包含了一個(gè)DIB。一個(gè)BMP文件大體上分成如下4個(gè)部分:bfType=”BM”

bfSize

bfReserved1

bfType=”BM”

bfSize

bfReserved1

bfReserved2

bfOffBits

位圖文件頭(只用于BMP文件)biSize

biWidth

biSize

biWidth

biHeightbiPlanes

biBitCount

biCompression

biSizeImage

biXPelsPerMeter

biYPelsPerMeter

biClrUsed

biClrImportant

位圖信息頭單色DIB有2個(gè)表項(xiàng)

16色DIB有16個(gè)表項(xiàng)或更少256色DIB有256個(gè)表項(xiàng)或更少

單色DIB有2個(gè)表項(xiàng)

16色DIB有16個(gè)表項(xiàng)或更少256色DIB有256個(gè)表項(xiàng)或更少

真彩色DIB沒有調(diào)色板

每個(gè)表項(xiàng)長(zhǎng)度為4字節(jié)(32位)像素按照每行每列的順序排列

每一行的字節(jié)數(shù)必須是4的整數(shù)調(diào)色板DIBPirxelsDIB圖像數(shù)據(jù)2.3圖像的幾何變換基礎(chǔ)知識(shí)圖像的幾何變換,通常包括圖像的平移、圖像的鏡像變換、圖像的轉(zhuǎn)置、圖像的縮放和圖像的旋轉(zhuǎn)等。程序結(jié)束圖像的縮放圖像的轉(zhuǎn)置圖像的鏡像圖像的平移程序開始讀寫B(tài)MP圖像圖像的旋轉(zhuǎn)程序結(jié)束圖像的縮放圖像的轉(zhuǎn)置圖像的鏡像圖像的平移程序開始讀寫B(tài)MP圖像圖像的旋轉(zhuǎn)圖2.1程序基本框架圖2.3.1圖像的平移圖像的平移是幾何變換中最簡(jiǎn)單的變換之一。圖像平移就是將圖像中所有的點(diǎn)都按照指定的平移量水平、垂直移動(dòng)。設(shè)(x0,y0)坐標(biāo)將變?yōu)椋▁1,y1)。顯然(x0,y0)和(x1,y1)的關(guān)系如下:x1=x0+tx用矩陣表示如下:x1對(duì)該矩陣求逆,可以得到逆變換:x0這樣,平移后的圖像上的每一點(diǎn)都可以在原圖像中找到對(duì)應(yīng)的點(diǎn)。例如,對(duì)于新圖中的(0,0)像素,代入上面的方程組,可以求出對(duì)應(yīng)原圖中的像素(-tx,-ty)。如果tx或ty大于0,則(-tx,-ty)不在原圖中。對(duì)于不在原圖中的點(diǎn),可以直接將它的像素值統(tǒng)一設(shè)置為0或則255(對(duì)于灰度圖就是黑色或白色)。同樣,若有點(diǎn)不在原圖中,也就說明原圖中有點(diǎn)被移出顯示區(qū)域。如果不想丟失被移出的部分圖像,可以將新生成的圖像寬度擴(kuò)大|tx|,高度擴(kuò)大|ty|。2.3.2圖像的鏡像圖像的鏡像變換分為兩種:一種是水平鏡像,另外一種是垂直鏡像。圖像的水平鏡像操作是將圖像的左半部分和右半部分以圖像垂直中軸線為中心鏡像進(jìn)行對(duì)換;圖像的垂直鏡像操作是將圖像上半部分和下半部分以圖像水平中軸線為中心鏡像進(jìn)行對(duì)換。設(shè)圖像高度為lHeight,寬度為lWidth,原圖中(x0,y0)經(jīng)過水平鏡像后坐標(biāo)將變?yōu)椋╨Width-x0,y0),其矩陣表達(dá)式為:x1逆運(yùn)算表達(dá)式為:x0y0同樣,(x0,y0)經(jīng)過垂直鏡像后坐標(biāo)將變?yōu)椋▁0,lHeight-y0),其矩陣表達(dá)式為:x1逆運(yùn)算矩陣表達(dá)式為:x0y012.3.3圖像的轉(zhuǎn)置圖像的轉(zhuǎn)置操作是將圖像像素的x坐標(biāo)和y坐標(biāo)互換。該操作將改變圖像的大小,圖像的高度和寬度將互換。轉(zhuǎn)置表達(dá)式:x1它的逆矩陣表達(dá)式:x0y012.3.4圖像的縮放上面的幾種圖像幾何變換中都是1:1的變換,而圖像的縮放操作將會(huì)改變圖像的大小,產(chǎn)生的圖像中的像素可能在原圖中找不到相應(yīng)的像素點(diǎn),這樣就必須進(jìn)行近似處理。一般的方法是直接賦值為和它最相近的像素值,也可以通過一些插值算法來計(jì)算。下面的代碼直接采用了前一種做法。假設(shè)圖像x軸方向縮放比率為fx,y軸方向縮放比率為fy,那么原圖中點(diǎn)(x0,y0)對(duì)應(yīng)與新圖中的點(diǎn)(x1,y1)的轉(zhuǎn)換矩陣為:x1其逆運(yùn)算如下:x0y01例如,當(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ò)大圖像范圍以顯示所有的圖像??梢酝茖?dǎo)一下旋轉(zhuǎn)運(yùn)算的變換公式。如下圖所示,點(diǎn)(x0,y0)經(jīng)過旋轉(zhuǎn)θ度后坐標(biāo)變成(x1,y1)。在旋轉(zhuǎn)前:x0=γcos(θ)轉(zhuǎn)置后:x1=γcosα-θx1其逆運(yùn)算如下:x0有了上面的轉(zhuǎn)換公式,就可以非常方便的編寫出實(shí)現(xiàn)圖像旋轉(zhuǎn)的函數(shù)。首先應(yīng)計(jì)算出公式中需要的幾個(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-1fDstX1,fDstY1fDstX2,fDstY2fDstX1,fDstY1fDstX1,fDstY1則新圖像的寬度lNewWidth和高度lNewHeight為:lNewWidth=maxfDstX4-fDstX1lNewHeight=maxfDstY4-fDstY1令f1=-ccosθ-dsinθ+af2=csinθ-dcosθ+b,x0=x12.4Visual

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ā)響應(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ù)的支持能使程序更好的模塊化,并且通過向?qū)С绦虼蟠蠛?jiǎn)化了庫(kù)資源的使用和應(yīng)用程序的開發(fā),正由于VC具有明顯的優(yōu)勢(shì),因而我選擇了它來作為數(shù)字圖像幾何變換的開發(fā)工具。在本程序的開發(fā)過程中,VC的核心知識(shí)、消息映射機(jī)制、對(duì)話框控件編程等都得到了生動(dòng)的體現(xiàn)和靈活的應(yīng)用。三、實(shí)驗(yàn)步驟及結(jié)果3.1通過API函數(shù)SetWorldTransForm實(shí)現(xiàn)圖像幾何變換API函數(shù)SetWorldTransForm實(shí)現(xiàn)圖像幾何變換使用XFORM來控制DC時(shí),需要先設(shè)置繪圖模式SetGraphicsMode為GM_ADVANCED,再用SetWorldTransform。否則SetWorldTransform函數(shù)會(huì)失敗。setWorldTransForm內(nèi)部的算法其實(shí)相當(dāng)于用線性代數(shù)里矩陣與一個(gè)向量相乘的辦法來解決圖形的變換,只要我們知道要乘上的變換方程是哪一個(gè),就能進(jìn)行各種變換(不止是旋轉(zhuǎn)),這個(gè)函數(shù)是對(duì)一個(gè)設(shè)備上下文DC進(jìn)行操作,通過坐標(biāo)轉(zhuǎn)換來實(shí)現(xiàn)各種功能的。函數(shù)原型:intSetGraphicsMode(HDChdc,intiMode);

參數(shù):hdc:指向設(shè)備環(huán)境的句柄。

iMode:指定圖形模式,該參數(shù)取值參看MSDN函數(shù)原型:BOOLSetWorldTransform(HDChdc,CONSTXFORM*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

+

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;于是,我們可以得到SetWorldTransForm的一組參數(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屬性改為“Resizing”,為其添加一些控件并未其中的而一些控件關(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=(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);}實(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_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);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.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+m_iPanLeft);xform.eDy=(float)(centerPt.y-cos(fangle)*centerPt.y-sin(fangle)*centerPt.x+m_iPanRight);SetWorldTransform(hDc,&xform);}實(shí)驗(yàn)結(jié)果:平移前的圖像橫向平移56.5縱向平移45的圖像橫向平移56縱向平移45且旋轉(zhuǎn)45°橫向平移-56縱向平移-45的圖像放大2倍的圖像3.2通過像素來實(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ǔ),圖像線性變換,圖像灰度拉伸等。然后為菜單欄添加一些新的菜單最后在視圖類為新添加的菜單項(xiàng)添加消息處理函數(shù)3.2.1圖像的平移有了上面的理論基礎(chǔ),可以十分容易的用Visual

C++來實(shí)現(xiàn)圖像的平移。在這里,只介紹灰度圖像的平移,因?yàn)榛叶葓D像每個(gè)像素位數(shù)正好是8位,即1個(gè)字節(jié),這樣,可以不必考慮拼湊字節(jié)的問題。而且由于灰度圖調(diào)色板的特殊性,處理時(shí)不必考慮調(diào)色板的問題。根據(jù)上面的公式可以得到圖像的平移程序流程圖:程序開始程序開始單擊“文件”單擊“文件”->“打開”打開一幅圖像單擊單擊“幾何變換”->圖像平移獲取水平平移量和垂直平移量獲取水平平移量和垂直平移量計(jì)算指向新計(jì)算指向新DIB第i行,第j個(gè)像素的指針提示用戶將該像素賦值為255

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖復(fù)制平移后的圖像直接復(fù)制像素判斷平移是否成功計(jì)算指向原DIB在該坐標(biāo)下像素的指針計(jì)算該像素在原DIB中的坐標(biāo)判斷坐標(biāo)是否在原圖范圍內(nèi)提示用戶將該像素賦值為255

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖復(fù)制平移后的圖像直接復(fù)制像素判斷平移是否成功計(jì)算指向原DIB在該坐標(biāo)下像素的指針計(jì)算該像素在原DIB中的坐標(biāo)判斷坐標(biāo)是否在原圖范圍內(nèi)否否否否 圖3.1圖像平移程序流程圖平移實(shí)現(xiàn)代碼:voidCImg_TransformView::OnGeomTran(){CImg_TransformDoc*pDoc=GetDocument(); LPSTR lpDIB;LPSTRlpDIBBits; lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); if(::DIBNumColors(lpDIB)!=256) {MessageBox("目前只支持256色位圖的平移!","系統(tǒng)提示",MB_ICONINFORMATION|MB_OK); ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); 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("分配內(nèi)存失?。?,"系統(tǒng)提示",MB_ICONINFORMATION|MB_OK);} ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB());}平移實(shí)現(xiàn)結(jié)果:平移前的圖像水平平移50垂直平移50的圖像3.2.2圖像的鏡像圖像的鏡像變換分為兩種:一種是水平鏡像,另外一種是垂直鏡像。圖像的水平鏡像操作是將圖像的左半部分和右半部分以圖像垂直中軸線為中心鏡像進(jìn)行對(duì)換;圖像的垂直鏡像操作是將圖像上半部分和下半部分以圖像水平中軸線為中心鏡像進(jìn)行對(duì)換。按照上面的變換公式,可以非常簡(jiǎn)單的實(shí)現(xiàn)圖像的水平和垂直鏡像操作。下圖是鏡像操作的程序流程圖:程序開始程序開始單擊單擊“文件”->“打開”打開一幅圖像否否是否水平鏡像是否水平鏡像針對(duì)每行圖像左半部分進(jìn)行操作針對(duì)上半圖像進(jìn)行操作針對(duì)每行圖像左半部分進(jìn)行操作針對(duì)上半圖像進(jìn)行操作操作計(jì)算指向倒數(shù)第i計(jì)算指向倒數(shù)第i行像素起點(diǎn)的指針計(jì)算指向倒數(shù)第i行,第j個(gè)像素的指針計(jì)算指向第i行像素起點(diǎn)的指針計(jì)算指向倒數(shù)第計(jì)算指向第i行像素起點(diǎn)的指針計(jì)算指向倒數(shù)第i行,倒數(shù)第j個(gè)像素的指針備份一行備份一個(gè)像素備份一行備份一個(gè)像素將倒數(shù)第i將倒數(shù)第i行像素復(fù)制到第i行將倒數(shù)第i行,第j個(gè)像素復(fù)制到倒數(shù)第i行,倒數(shù)第j個(gè)像素將倒數(shù)第i行,倒數(shù)第將倒數(shù)第i行,倒數(shù)第j個(gè)像素復(fù)制到倒數(shù)第i行,第j個(gè)像素將第將第i行像素復(fù)制到倒數(shù)第i行否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷鏡像是否成功否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷鏡像是否成功鏡像實(shí)現(xiàn)的代碼:voidCImg_TransformView::OnGeomMirv(){CImg_TransformDoc*pDoc=GetDocument(); LPSTR lpDIB;LPSTRlpDIBBits; lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); if(::DIBNumColors(lpDIB)!=256) {MessageBox("目前只支持256色位圖的鏡像!","系統(tǒng)提示",MB_ICONINFORMATION|MB_OK); ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); return; } intbDirection; CMirvDlgdlg;if(dlg.DoModal()!=IDOK) {return;} bDirection=dlg.m_bDirection;deletedlg; lpDIBBits=::FindDIBBits(lpDIB); if(MirrorDIB(lpDIBBits,::DIBWidth(lpDIB),::DIBHeight(lpDIB),bDirection)) { pDoc->SetModifiedFlag(TRUE);pDoc->UpdateAllViews(NULL); } else {MessageBox("分配內(nèi)存失??!","系統(tǒng)提示",MB_ICONINFORMATION|MB_OK);} ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB())}鏡像實(shí)驗(yàn)結(jié)果:鏡像前的圖像水平鏡像的圖像垂直鏡像的圖像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)行操作針對(duì)每行圖像每列進(jìn)行操作計(jì)算指向原計(jì)算指向原DIB第i行,第j個(gè)像素的指針計(jì)算指向轉(zhuǎn)置DIB第計(jì)算指向轉(zhuǎn)置DIB第j行,第i個(gè)像素的指針復(fù)制轉(zhuǎn)置后的圖像復(fù)制像素復(fù)制轉(zhuǎn)置后的圖像復(fù)制像素互換互換DIB中圖像的高寬否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功圖3.3圖像轉(zhuǎn)置的程序流程圖圖像轉(zhuǎn)置代碼:voidCImg_TransformView::OnGeomTrpo(){ CImg_TransformDoc*pDoc=GetDocument(); LPSTR lpDIB; LPSTRlpDIBBits; lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); if(::DIBNumColors(lpDIB)!=256) {MessageBox("目前只支持256色位圖的轉(zhuǎn)置!","系統(tǒng)提示",MB_ICONINFORMATION|MB_OK); ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); return; } if(TransposeDIB(lpDIB)) { pDoc->SetModifiedFlag(TRUE); pDoc->UpdateAllViews(NULL); } else { MessageBox("分配內(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)生的圖像中的像素可能在原圖中找不到相應(yīng)的像素點(diǎn),這樣就必須進(jìn)行近似處理。一般的方法是直接賦值為和它最相近的像素值,也可以通過一些插值算法來計(jì)算。下面的代碼直接采用了前一種做法。按照上面的轉(zhuǎn)換公式,可以容易的寫出圖像的縮放程序流程圖:程序開始程序開始單擊“文件”單擊“文件”->“打開”打開一幅圖像單擊單擊“幾何變換”->圖像縮放獲取水平縮放量和垂直縮放量獲取水平縮放量和垂直縮放量更新更新DIB中圖像的高度和寬度針對(duì)圖像每行每列進(jìn)行操作針對(duì)圖像每行每列進(jìn)行操作計(jì)算指向原DIB計(jì)算指向原DIB第i行,第j個(gè)像素的指針計(jì)算指向轉(zhuǎn)置DIB第j行,第i個(gè)像素的指針復(fù)制轉(zhuǎn)置后的圖像復(fù)制像素互換DIB中圖像的高寬否提示用戶

程序結(jié)束是計(jì)算指向轉(zhuǎn)置DIB第j行,第i個(gè)像素的指針復(fù)制轉(zhuǎn)置后的圖像復(fù)制像素互換DIB中圖像的高寬否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功3.4圖像縮放的程序流程圖圖像縮放代碼:voidCImg_TransformView::OnGeomZoom(){CImg_TransformDoc*pDoc=GetDocument(); LPSTRlpDIB; lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); if(::DIBNumColors(lpDIB)!=256) {MessageBox("目前只支持256色位圖的縮放!","系統(tǒng)提示",MB_ICONINFORMATION|MB_OK); ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); return; } floatfXZoomRatio; floatfYZoomRatio; CZoomDlgdlg; dlg.m_XZoom=0.5; dlg.m_YZoom=0.5;if(dlg.DoModal()!=IDOK) {return;} fXZoomRatio=dlg.m_XZoom;fYZoomRatio=dlg.m_YZoom; deletedlg; HDIBhNewDIB=NULL; hNewDIB=(HDIB)ZoomDIB(lpDIB,fXZoomRatio,fYZoomRatio); if(hNewDIB!=NULL) { 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é)果:縮放前的圖像水平和垂直都縮小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)角度的正弦和余弦程序開始單擊“文件”->“打開”打開一幅圖像單擊“幾何變換”->圖像旋轉(zhuǎn)獲取旋轉(zhuǎn)角度計(jì)算旋轉(zhuǎn)角度的正弦和余弦

計(jì)算原圖和新圖四個(gè)角的坐標(biāo)否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功否提示用戶

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖判斷轉(zhuǎn)置是否成功計(jì)算旋轉(zhuǎn)后圖像實(shí)際寬度和高度計(jì)算旋轉(zhuǎn)后圖像實(shí)際寬度和高度針對(duì)圖像每行每列進(jìn)行操作針對(duì)圖像每行每列進(jìn)行操作計(jì)算指向新DIB計(jì)算指向新DIB第i行,第j個(gè)像素的指針計(jì)算該像素在原DIB計(jì)算該像素在原DIB中的坐標(biāo)否否提示用戶將該像素賦值為255

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖復(fù)制平移后的圖像直接復(fù)制像素判斷平移是否成功計(jì)算指向原DIB在該坐標(biāo)下像素的指針判斷坐標(biāo)是否在原圖范圍內(nèi)否否提示用戶將該像素賦值為255

程序結(jié)束是

程序結(jié)束設(shè)置臟標(biāo)記更新視圖復(fù)制平移后的圖像直接復(fù)制像素判斷平移是否成功計(jì)算指向原DIB在該坐標(biāo)下像素的指針判斷坐標(biāo)是否在原圖范圍內(nèi) 圖3.5圖像旋轉(zhuǎn)的程序流程圖圖像旋轉(zhuǎn)代碼:voidCImg_TransformView::OnGeomRota(){ CImg_TransformDoc*pDoc=GetDocument(); LPSTRlpDIB; lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHDIB()); {MessageBox("目前只支持256色位圖的縮放!","系統(tǒng)提示",MB_ICONINFORMATION|MB_OK); ::GlobalUnlock((HGLOBAL)pDoc->GetHDIB()); return; } floatiRotateAngle; CRotateDlgdlg; dlg.m_iRotateAngle=90;if(dlg.DoModal()!=IDOK) {return;} iRotateAngle=dlg.m_iRotateAngle; deletedlg; HDIBhNewDIB=NULL; hNewDIB=(HDIB)RotateDIB(lpDIB,iRotateAngle); if(hNewDIB!=NULL) { 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());}旋轉(zhuǎn)實(shí)驗(yàn)結(jié)果:旋轉(zhuǎn)前圖像旋轉(zhuǎn)65°的圖像四、結(jié)論與體會(huì)本例只針對(duì)256級(jí)灰度圖進(jìn)行處理。由于本程序首先要實(shí)現(xiàn)任意BMP圖像的讀寫,打印,以及剪貼板操作,故用VisualC++創(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)典的圖像幾何變換功能。包括:圖像的平移。經(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)。圖像的鏡像。圖像的水平鏡像操作是將圖像的左半部分和右半部分以圖像垂直中軸線為中心鏡像進(jìn)行對(duì)換;圖像的垂直鏡像操作是將圖像上半部分和下半部分以圖像水

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論