王真明



摘要:目前,數字圖像處理民已廣泛應用于工業、醫療保健、航空航天、軍事等領域。隨著信息高速公路、數字地球概念的提出以及Intemet的飛速發展,數字圖像處理由于具有信息量大、傳輸速度快、作用距離遠等一系列優點,必將成為人類獲取信息的重要來源和利用信息的重要手段。該文介紹了數字圖像的基本知識,數字圖像的幾何運算系統的開發原理,主要實現功能、子模塊設計及實現技術。其中,重點介紹了通過對像素的幾何運算實現圖像的各種幾何變換的原理和算法實現。
關鍵詞:數字圖像;像素;幾何運算
中圖分類號:TP391 文獻標識碼:A
文章編號:1009-3044(2020)03-0209-04
數字圖像處理技術與理論是計算機應用的一個重要領域,數字圖像的幾何運算是數字圖像處理的一個重要組成部分。人類感知圖像是通過視覺系統接收物體透射光或反射光在大腦中形成的印象或認識。人類獲取外界信息約80%左右是來自視覺所接收的圖像信息。圖像的幾何運算就是對其進行平移、縮放、鏡像、旋轉、轉置等處理,用于滿足實際需要。用計算機對圖像進行各種處理我們稱之為數字圖像處理。本文就是討論如何利用微軟的Visual C++開發工具來實現一些常用的數字圖像處理算法——數字圖像的幾何運算。
圖像分為黑白圖像和彩色圖像,其中黑白圖像又包括單色圖像和灰度圖像,灰度圖像是用0表示黑,255表示白,中間值表示灰色,用該字節的數值表示對應像素的灰度值或亮度值。彩色圖像一般使用RGB模式,其中R表示紅色,G表示綠色,B表示藍色,統稱為“三基色”,用這三種色彩的不同搭配,就可以形成各種不同的色彩。形成的圖像文件一般用BMP、JPEG、GIF等格式表示。
本系統的開發以圖像像素的幾何運算為原理,綜合了各學科(如數學、物理學、計算機學、系統工程等)較先進的成果形成的計算機圖像處理主要防采用兩大類方法:一類是在圖像空間中對圖像進行各種處理;另一類方法是把圖像進行變換,經過傅立葉變換或小波變換,變換到頻率域,在頻率域中進行各種處理,然后再變換回圖像的空間域,形成處理后的圖像。
圖像的幾何運算也稱為空間變換,是建立一幅圖像與其變換后的圖像中所有各點之間映射關系的函數。這些函數能唯一確定輸入圖像和輸出圖像中所有像素點之間的幾何對應關系。即:[x,y]-[X(u,v),Y(u,v)] 或[u,v]-[U(x,y),V(x,y)]
其中,[u,v]表示輸入圖像的像素坐標,[x,y]表示輸出圖像的像素坐標。X、Y、U、V表示空間幾何變換的映射函數,該函數唯一定義了輸入和輸出圖像中所有點之間的幾何對應關系。X、Y將輸入映射到輸出,稱為前向映射(Forward Mapping);U、V將輸出映射到輸入,稱為逆向映射(Inverse Mapping)。圖像的幾何運算應用得非常普遍,已廣泛應用于醫學成像、遙感圖像處理、計算機視覺以及電視、電影、多媒體廣告等影像處理中。本文介紹一些常用的圖像變換技術,包括圖像的平移、鏡像、轉置、旋轉、縮放等。
1)判斷并打開一幅256色BMP位圖顯示出來;
2)圖像平移:通過所給X、Y方向平移參數進行相應位移量的平行移動;
3)圖像縮放:通過所給X、Y方向的縮放參數進行相應倍數的縮小或放大;
4)圖像旋轉:通過所給旋轉度數進行順時針方向的旋轉;
5)圖像鏡像:實現對數字圖像的垂直鏡像或水平鏡像;
6)圖像轉置:通過把圖像的x坐標與y坐標互換實現圖像的轉置。
利用數學公式對圖像像素進行幾何運算和VC++的數字圖像處理技術為理論基礎,完成對圖像進行平移、鏡像、縮放、旋轉、轉置等幾何變換的算法實現,并實際設計實現上述功能。
1 打開位圖模塊
因灰度圖像每個像素位數正好是8位(1個字節),因此在進行圖像處理時不用考慮拼湊字節的問題。而且由于灰度圖調色板的特殊性,進行灰度圖像處理時不必考慮調色板的問題。這樣在介紹圖像處理時,一般采用灰度圖,為的是將重點放在算法本身。
系統調用Ondraw0函數,用GetDocument0獲取文檔,然后調用GetHDIBO獲取DIB,該函數主要用來繪制DIB對象。其中調用了StretchDIBits0或者SetDIBitsToDevice0來繪制DIB對象。輸出的設備由參數hDC指定;繪制的矩形區域由參數lpDCRect指定;輸出DIB的區域由參數lpDIBRect指定。再調用Paint-DIBO函數,在PaintDIBO中先鎖定DIB找到DIB圖像象素起始位置,獲取DIB調色板,并選中它,設置好顯示模式,最后判斷是原始大小,不用拉伸調用StretchDIBits0若不是原始大小,則調用SetDIBitsToDevice0來繪制DIB對象。
2 圖像平移
2.1 基本原理
所有的點都按照指定的平移量水平、垂直移動。如圖所示,設(x0,y0)為原圖像上的一點,圖像水平平移量為x,垂直平移量為v,則平移后點(x0,y0)坐標將變為(xl,yl)。
平移后圖像的每一個點都可以在原圖像中找到相對應的點。例如,對于新圖中的(0,0)像素,代人上面的方程組,可以求出對應原圖中的像素(-x,-y)。如果x大于0,則點(-x,-y)不在原圖中。對于不在原圖中的點,可以直接將它的像素值統一設置為255。同樣,若有點不在原圖中,也就說明原圖中有點被移出顯示區域。如果不想丟失被移出的部分圖像,可以將新生成的圖像寬度擴大lxl.高度擴大lyl。
2.2 平移模塊實現
首先取得原圖的數據區指針.通過對話框輸入偏移量x,y,開辟一個同樣大小的緩沖區,再對原圖依次循環每個像素,每讀入一個像素點(x0,y0),根據它的坐標(x0,y0)找到目標圖像的位置(xl=xO+x,yl=yO+y),將像素(x0,y0)處的顏色值賦給新圖中的(xl,yl)。
for(i=0;i
{
for(j=0;j
{
//指向新DIB第i行,第j個象素的指針
//由于DIB中圖像第一行其實保存在最后一行的位置,因此lpDst
//值不是(char *)lpNewDIBBits+ lLineBytes{i+j,而是
//(char *)lpNewDIBBits+ lLineBytes*(lHeight -1 -i)+j
lpDst= (char *)lpNewDIBBits+ ILineBytes半(IHeight -1 -i)+j;
//計算該象素在源DIB中的坐標
i0=i- lYOffset;
j0=j- lXOffset;
//判斷是否在源圖范圍內
if(00>=0)&&(j0< IWidth)&&(i0>=0)&&(i0< IHeight》
{
//指向源DIB第i0行,第j0個象素的指針
//同樣要注意DIB上下倒置的問題
lpSrc=(char *)lpDIBBits+lLineBytes*(lHeight -1- i0)+j0;
*lpDst= *lpSrc; //復制象素
)
elsef
*《unsigned char*)lpDst)= 255; 11源圖中沒有的象素,直接賦值255
)))
3 圖像縮放模塊
3.1 基本原理
圖像x軸方向縮放比率nx,y軸方向縮放比率是ny,那么原圖中點(x0,y0)對應與新圖中的點(xl,v1)的轉換矩陣為:
例如當nx=ny=0.5時,圖像被縮到原圖一半大小,此時縮小后圖像中的(0,0)像素對應于原圖中的(0,0)像素;(0,1)像素對應于原圖中的(0,2)像素,(1,0)像素對應于原圖中的(2,o)像素,以此類推。在原圖基礎上,每行隔一個像素取一點,每隔一行進行操作。同理,當nx=ny=2時,圖像就會放大2倍,放大后圖像中的(0,0)對應于原圖中的(0,0);(0,1)對應于原圖中的(0,0.5),該像素不存在,可以近似為(0,0)也可以近似為(0,1);(0,2)對應于原圖中的(0,1);(1,0)對應于原圖中的(0.5,0)-(0,0)或(1,0);(2,0)對應于原圖中的(1,0)。其實就是將原圖每行中的像素重復取值一遍,然后每行重復一次。
如圖3、圖4分別是放大前和放大后的圖像。
3.2 縮放模塊實現
先取得原圖的數據區指針,通過對話框獲得放大整數比例:nx,ny,更改圖像的寬度和高度,每個像素依次循環。計算該像素在原圖中的坐標,將原圖的像素值賦給目標像素相應位置nxXny個值。
for(i=0;i
{
//針對圖像每列進行操作
for(j=0;j
{
,/指向新DIB第i行,第j個象素的指針
//此處寬度和高度是新DIB的寬度和高度
lpDst=(char *)lpNewDIBBits+lNewLineBytes* (lNe-wHeight -1 -i)+j;
//計算該象素在源DIB中的坐標
i0= (LONG)(i/fYZoomRatio+ 0.5);
j0= (LONG)(j /fXZoomRatio+ 0.5)
//判斷是否在源圖范圍內
if( (j0>=o)&&(j0< IWidth)&&(i0>=0)&&(i0< lHeight》
{
//指向源DIB第i0行,第j0個象素的指針
lpSrc=(char *)lpDIBBits+lLineBytes木(lHeight -1-i0)+j0;
*lpDst= *lpSrc; //復制象素
1else
{
*《unsigned char*)lpDst)= 255; 11對源圖中沒有的象素,直接賦值255
)))
4 圖像鏡像模塊
4.1 基本原理
設圖像高度為IHeight,寬度為IWidth,原圖中(x0,y0)經過水平鏡像后坐標將變為(lWidth-x0,y0),其矩陣表達式為:
4.2 鏡像模塊實現
首先取得原圖的數據區指針,開辟一個同樣大小的緩沖區,每個像素依次循環。在水平鏡像中,將原圖中的像素點的水平坐標變成鏡像后的坐標(用圖像的寬度減去坐標值)再顯示到圖像上。垂直鏡像中,則對垂直坐標做相應的處理。
按照上面的變換公式,實現水平和垂直鏡像的算法,bdi-rection真時表示水平鏡像,否則為垂直鏡像:
//判斷鏡像方式
if (bDirection)
{
//水平鏡像
//針對圖像每行進行操作
for(i=0;i
{
//針對每行圖像左半部分進行操作
for(j=0;j
{
//指向倒數第i行,第j個象素的指針
lpSrc= (char *)lpDIBBits+ lLineBytes*i+j;
//指向倒數第i行,倒數第j個象素的指針
lpDst= (char *)lpDIBBits+ lLineBytes*(i+1)-j;
//|備份—個象素
*lpBits= *lpDst;
//將倒數第i行第j個象素復制到倒數第i行倒數第j個象素
*lpDst= *lpSrc;
//將倒數第i行倒數第j個象素復制到倒數第i行第j個象素
*lpSrc= *lpBits;
)})
else//垂直鏡像
{//針對上半圖像進行操作
for(i=0;i
{//指向倒數第i行象素起點的指針
lpSrc= (char *)lpDIBBits+ ILineBytes*i;
//指向第i行象素起點的指針
lpDst= (char *)lpDIBBits+ lLineBytes*(lHeight -i -1);
//備份一行,寬度為lWidth
memcpy(lpBits, lpDst, lLineBytes);
//將倒數第i行象素復制到第i行
memcpy(lpDst, lpSrc, lLineBytes);
//將第i行象素復制到倒數第i行
memcpy(lpSrc, lpBits, lLineBytes);
}}
5 圖像旋轉模塊
5.1 旋轉基本原理
圖像的旋轉是以圖像的中心為原點,旋轉一定的角度。旋轉后,圖像的大小一般會改變我們可以把轉出顯示區的圖像截去,也可以擴大圖像范圍以顯示所有的圖像,這里我們實現后者。如圖5所示,點(x0,y0)經過旋轉0度后坐標變成(xl,yl)。
上述旋轉是繞坐標軸原點(0,0)進行的,如果是繞一個指定點(a,b)旋轉,則先要將坐標系平移到該點,再進行旋轉,然后平移回新的坐標原點,在此不再詳述。
5.2 旋轉模塊實現
//針對圖像每行進行操作
for(i=0;i
{
//針對圖像每列進行操作
for(j=0;j
{//指向新DIB第i行,第j個象素的指針,此處寬度和高度是新DIB的寬度和高度
lpDst=(char *)lpNewDIBBits+lNewLineBytes* (lNe-wHeight -l -i) +j;
//計算該象素在源DIB中的坐標
i0= (LONG) (-《float)j)4f'Sina+《float)i)4fCosa+ f2+ 0.5);
j0= (LONG)(《float)j)4 fCosa+《float)i)4 fSina +fl+ 0.5);
//判斷是否在源圖范圍內
if((j0>=0)&&(j0< IWidth)&&(i0>=0)&&(i0< IHeight》
{
//指向源DIB第i0行,第j0個象素的指針
lpSrc=(char *)lpDIBBits+lLineBytes*(IHeight -1-i0)+j0;
//復制象素
*lpDst= *lpSrc;
1else
{
//對于源圖中沒有的象素,直接賦值為255
*《unsigned char*)lpDst)= 255;
}}}
6 圖像轉置模塊
6.1 轉置基本原理
圖像的轉置(transpose)操作是將圖像像素的x坐標和y坐標互換。該操作將改變圖像的高度和寬度,轉置后圖像的高度和寬度將互換。即:
x0= yl
yo= xl
6.2 轉置模塊實現
圖像的轉置的實現和圖像鏡像變換類似,不同之處在于圖像轉置后DIB的頭文件也要進行相應的改變,主要是將頭文件中圖像高度和寬度信息更新。因此傳遞給圖像轉置函數的參數是直接指向DIB的指針,而不是直接指向DIB像素的指針。下面給出圖像轉置函數的算法。
//針對圖像每行進行操作
for(i=0;i
{for(j=0;j
{//指向源DIB第i行,第j個象素的指針
lpSrc= (char *)lpDIBBits+ lLineBytes*(lHeight -1 -i)+j;
//指向轉置DIB第j行,第i個象素的指針
//注意此處lWidth和lHeight是源DIB的寬度和高度,應該互換
lpDst= (char *)lpNewDIBBits+ lNewLineBytes*(IWidth -1一j)+i;
//復制象素
*lpDst= *lpSrc;
}}
數字圖像處理技術博大精深,不但需要熟練掌握一門程序開發語言,還需要深厚的數學功底,自20世紀60年代第三代數字計算機問世以后,數字圖像處理技術出現了空前的發展,在諸如航空航天、生物醫學工程、通信工程、文化藝術、電子商務等等領域都有廣泛應用。本文利用Visual C++這個開發平臺只是拋磚引玉,希望和廣大讀者共同交流學習。
參考文獻:
[1]楊淑瑩,邊奠英.VC++圖像處理程序設計[M].北京:清華大學出版社,2003.
[2]歐珊瑚,王倩麗,朱哲瑜.Visual C++.NET數字圖像處理技術與應用[M].北京:清華大學出版社,2004.
[3]陳兵旗,孫明.Visual C++實用圖像處理[M].北京:清華大學出版社,2004.
[4]鐘志光,盧君,劉偉榮.Visual C++.NET數字圖像處理實例與解析[M].北京:清華大學出版社,2003.
[5]何斌,馬天予,王運堅,等.Visual C++數字圖像處理[M].北京:人民郵電出版社,2002.
[6]譚浩強.Visual C++ 6.0實用教程[M].北京:電子工業出版社。2001.
[7]朱志剛,林學訚,石定機,等,數字圖像處理[M].北京:電子工業出版社。2002.
[8]譚浩強.Visual C++ 6.0實用教程[M].北京:電子工業出版社,2001.
[9]鄭阿奇.Visual C++實用教程[M].2版.北京:電子工業出版社,2003.