版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第第頁(yè)實(shí)驗(yàn)三圖像編碼一、實(shí)驗(yàn)內(nèi)容:用Matlab語(yǔ)言、C語(yǔ)言或C++語(yǔ)言編制圖像處理軟件,對(duì)某幅圖像進(jìn)行時(shí)域和頻域的編碼壓縮。二、實(shí)驗(yàn)?zāi)康暮鸵饬x:1.掌握哈夫曼編碼、香農(nóng)-范諾編碼、行程編碼2.了解圖像壓縮國(guó)際標(biāo)準(zhǔn)三、實(shí)驗(yàn)原理與主要框架:3.1實(shí)驗(yàn)所用編程環(huán)境:VisualC++6.0(簡(jiǎn)稱(chēng)VC)3.2實(shí)驗(yàn)處理的對(duì)象:256色的BMP(BITMAP)格式圖像BMP(BITMAP)位圖的文件結(jié)構(gòu):(如圖3.1)圖3.1位圖的文件結(jié)構(gòu)具體組成圖:3.3數(shù)字圖像基本概念數(shù)字圖像是連續(xù)圖像的一種近似表示,通常用由采樣點(diǎn)的值所組成的矩陣來(lái)表示:每一個(gè)采樣單元叫做一個(gè)像素(pixel),上式(2.1)中,M、N分別為數(shù)字圖像在橫(行)、縱(列)方向上的像素總數(shù)。在計(jì)算機(jī)內(nèi)通常用二維數(shù)組來(lái)表示數(shù)字圖像的矩陣,把像素按不同的方式進(jìn)行組織或存儲(chǔ),就得到不同的圖像格式,把圖像數(shù)據(jù)存成文件就得到圖像文件。圖像文件按其數(shù)字圖像格式的不同一般具有不同的擴(kuò)展名。最常見(jiàn)的圖像格式是位圖格式,其文件名以BMP為擴(kuò)展名。圖像數(shù)字化的精度包括兩部分,即分辨率和顏色深度。分辨率指圖像數(shù)字化的空間精細(xì)度,有顯示分辨率和圖像分辨率兩種。數(shù)字圖像的顏色深度表示每一像素的顏色值所占的二進(jìn)制位數(shù)。顏色深度越大則能表示的顏色數(shù)目越多。顏色深度的不同,就產(chǎn)生不同種類(lèi)的圖像文件,在計(jì)算機(jī)中常使用圖像文件的類(lèi)型有單色圖像、灰度圖像、偽彩色圖像和24位真彩色圖像。它們之間的關(guān)系取決于數(shù)字圖像采用的顏色表示法。常用的顏色表示法有RGB、CMYK、HSL和YUV等。數(shù)字圖像的數(shù)據(jù)容量非常龐大,如以24位真彩色表示像素為640*480的數(shù)字圖像,所需要的數(shù)據(jù)量為900KB,所以需要對(duì)數(shù)字圖像進(jìn)行數(shù)據(jù)壓縮。數(shù)據(jù)壓縮包括數(shù)據(jù)壓縮編碼和壓縮數(shù)據(jù)解碼兩個(gè)過(guò)程。圖像壓縮的基本原則包括:(1)編碼重復(fù)壓縮:按照編碼重復(fù)的概率大小做壓縮編碼,壓縮重復(fù)概率大的編碼,可以節(jié)省一些存儲(chǔ)空間。(2)像素間重復(fù)壓縮:前后像素間存在的某種程度的相關(guān),如存在相同的背景圖像等,簡(jiǎn)化編碼以節(jié)省空間。(3)視覺(jué)重復(fù)壓縮:由于入眼的生理構(gòu)造,就算在像素之間少了幾個(gè)像素,眼睛也看不出來(lái)。但是,只是在某些情況中才可以允許這種失真性較大的應(yīng)用。主要的數(shù)字圖像壓縮標(biāo)準(zhǔn)是JPEG(JointPictureExpertGroup)標(biāo)準(zhǔn)。數(shù)字圖像的采集設(shè)備主要有掃描儀、數(shù)字相機(jī)和圖像采集卡等。通過(guò)對(duì)數(shù)字圖像進(jìn)行一定的處理,即圖像處理,可在一定程度上改善圖像的分辨質(zhì)量和形成特殊的視覺(jué)效果。數(shù)字圖像處理由數(shù)字圖像處理系統(tǒng)完成,其結(jié)構(gòu)主要包括圖像采集系統(tǒng)、計(jì)算機(jī)圖像處理系統(tǒng)和圖像輸出系統(tǒng)三部分。3.4圖像的編碼圖像的編碼包括圖像的離哈夫曼編碼、香農(nóng)-范諾編碼、行程編碼,基本框架(如圖3.2)和圖像編碼菜單設(shè)計(jì)圖(如圖3.3)如下:圖3.2圖像編碼流程圖圖3.3bmp圖像編碼菜單設(shè)計(jì)圖數(shù)字圖像編碼技術(shù):4.1哈夫曼編碼根據(jù)信息論中信源編碼理論,當(dāng)平均碼長(zhǎng)R大于等于圖像熵H時(shí),總可設(shè)計(jì)出一種無(wú)失真編碼。當(dāng)平均碼長(zhǎng)大于圖像熵時(shí),表明該編碼方法效率很低;當(dāng)平均碼長(zhǎng)等于或很接近于(但不大于)圖像熵時(shí),稱(chēng)此編碼方法為最佳編碼,此時(shí)不會(huì)引起圖像失真;當(dāng)平均碼長(zhǎng)小于圖像熵時(shí),壓縮比較高,但會(huì)引起圖像失真。在變長(zhǎng)編碼中,如果碼字長(zhǎng)度嚴(yán)格按照對(duì)應(yīng)符號(hào)出現(xiàn)的概率大小逆序排列,但其平均碼字長(zhǎng)度為最小,這就是變長(zhǎng)最佳編碼定理。變長(zhǎng)最佳編碼定理是哈夫曼編碼的理論基礎(chǔ)。4.1.1哈夫曼編碼基本原理哈夫曼(Huffman)編碼是一種常用的壓縮編碼方法,是Huffman于1952年為壓縮文本文件建立的,是一種效率比較高的變長(zhǎng)無(wú)失真信源編碼方法。它的基本原理是頻繁使用的數(shù)據(jù)用較短的代碼代替,較少使用的數(shù)據(jù)用較長(zhǎng)的代碼代替,每個(gè)數(shù)據(jù)的代碼各不相同。由于哈夫曼編碼是以信源概率分布為基礎(chǔ)的,但一般情況下無(wú)法事先知道信源的概率分布,因而通常采用對(duì)大量數(shù)據(jù)進(jìn)行統(tǒng)計(jì)后得到的近似分布來(lái)代替,這樣會(huì)導(dǎo)致實(shí)際應(yīng)用時(shí)哈夫曼編碼無(wú)法達(dá)到最佳性能。4.1.2哈夫曼編碼步驟下面來(lái)介紹哈夫曼編碼方法:(1)將輸入的符號(hào)(圖像中的灰度級(jí))按出現(xiàn)概率由小到大排列,即(2)將最小的兩個(gè)相加,形成一個(gè)新的概率集合(此時(shí)壓縮了一個(gè)),再按(1)重復(fù)直到只剩下兩個(gè)概率為止。下圖給出了一個(gè)實(shí)際信源符號(hào)的縮減過(guò)程。表3.1哈夫曼編碼中的信源符號(hào)縮減過(guò)程原始信源信源符號(hào)縮減步驟符號(hào)概率123450.020.040.060.060.060.120.120.120.120.160.160.160.160.20.240.20.20.20.240.360.40.40.40.40.40.40.6從最后的兩概率值開(kāi)始逐步向前給符號(hào)分配碼字長(zhǎng),每一步有兩個(gè)分支,以相同的規(guī)則各賦予一個(gè)二進(jìn)制碼。編碼過(guò)程如表3.2所示。表3.2哈夫曼編碼中的碼字分配過(guò)程原始信源按信源符號(hào)縮減逆向賦碼字符號(hào)概率碼字123450.02011110.04011100.0601110.0601100.0601100.120110.120100.120100.120100.160010.160010.160010.160010.20000.24010.20000.20000.20000.24010.36000.410.410.410.410.410.410.60同時(shí)也可以計(jì)算與編碼性能相關(guān)的幾個(gè)參數(shù):(1)信源的熵(3.1)(2)哈夫曼編碼的平均碼字長(zhǎng)(3.2)(3)哈夫曼編碼的效率(3.3)4.1.3哈夫曼編碼特點(diǎn)用哈夫曼編碼方法壓縮圖像數(shù)據(jù),對(duì)于不同的圖像,其壓縮效果和壓縮效率是不同的。當(dāng)各符號(hào)出現(xiàn)概率不同時(shí),編碼效率較高。而當(dāng)各符號(hào)出現(xiàn)的概率相等時(shí),實(shí)際上此時(shí)的哈夫曼編碼就已退化成等長(zhǎng)編碼,編碼效率較低。對(duì)灰度圖像的無(wú)損壓縮算法采用哈夫曼編碼,即對(duì)原圖像實(shí)行直接的編碼,該算法在恢復(fù)圖像的質(zhì)量上是極好的。但由于該算法對(duì)原圖像直接使用不等長(zhǎng)編碼壓縮,但沒(méi)有處理圖像各個(gè)像素間的相關(guān)性,從而使壓縮效率并不是很高,因此必須結(jié)合其它的壓縮方法同時(shí)使用以達(dá)到更高的壓縮比。4.2香農(nóng)-范諾編碼香農(nóng)-范諾(Shannon-Fannon)編碼也是一種常見(jiàn)的可變字長(zhǎng)編碼。與哈夫曼編碼相似,當(dāng)信源符號(hào)出現(xiàn)時(shí)的概率正好為2-i時(shí),采用香農(nóng)-范諾編碼同樣能達(dá)到100%的編碼效果。4.2.1香農(nóng)-范諾編碼基本原理香農(nóng)-范諾編碼的理論基礎(chǔ)是符號(hào)的碼字長(zhǎng)度Ni完全由該符號(hào)出現(xiàn)的概率來(lái)決定,即-logDPiNi-logDPi+1,式中D為編碼所用的數(shù)制。4.2.2香農(nóng)-范諾編碼步驟(1)將信源符號(hào)Xi按其出現(xiàn)概率Pi從小到大排序:(3.3)(2)將X分成兩個(gè)子集(3.4)并且保證成立或差不多成立。在本圖像壓縮編碼設(shè)計(jì)中是按前一個(gè)子集大于等于總和的一半來(lái)計(jì)算的。(3)給兩個(gè)子集賦不同的碼元值,如X1中的符號(hào)賦“1”,X2中的符號(hào)就賦“0”。(4)重復(fù)(2)、(3),即對(duì)每個(gè)子集再一分為二,并分別賦予不同碼元值,直到每個(gè)子集僅含一個(gè)信源符號(hào)為止。下面通過(guò)哈夫曼編碼中用過(guò)的同樣例子,說(shuō)明上述編碼過(guò)程。將信源(3.5)記為:(3.6)則其編碼過(guò)程如表3.3所示。表3.3香農(nóng)-范諾編碼過(guò)程碼字符號(hào)概率111111X10.02111111111110X20.04011110X30.0601110X40.120110X50.16010X60.200X70.404.2.3香農(nóng)-范諾編碼特點(diǎn)采用以上算法用VC具體實(shí)現(xiàn)對(duì)某一圖像進(jìn)行編碼,同時(shí)對(duì)編碼的有關(guān)評(píng)估參數(shù)如圖像熵值、平均碼長(zhǎng)、編碼效率進(jìn)行計(jì)算。為了便于編碼的顯示設(shè)計(jì)了編碼顯示對(duì)話框,在其中進(jìn)行編碼運(yùn)算并實(shí)現(xiàn)碼字的顯示。4.3行程編碼行程編碼又稱(chēng)行程長(zhǎng)度編碼(RunLengthEncoding,RLE),是一種熵編碼,其編碼原理相當(dāng)簡(jiǎn)單,即將具有相同值的連續(xù)串用其串長(zhǎng)和一個(gè)代表值來(lái)代替,該連續(xù)串就稱(chēng)為行程,串長(zhǎng)稱(chēng)為行程長(zhǎng)度。RLE壓縮編碼尤其適用于計(jì)算機(jī)生成的圖形圖像,對(duì)減少存儲(chǔ)容量很有效果。4.3.1行程編碼基本原理行程編碼分為定長(zhǎng)和不定長(zhǎng)編碼兩種。定長(zhǎng)編碼是指編碼的行程長(zhǎng)度所用的二進(jìn)制位數(shù)固定,而變長(zhǎng)形成編碼是指對(duì)不同范圍的行程長(zhǎng)度使用不同位數(shù)的二進(jìn)制進(jìn)行編碼。使用變長(zhǎng)行程編碼需要增加標(biāo)志位來(lái)表明所使用的二進(jìn)制位數(shù)。為了達(dá)到較好的壓縮效果,一般不單獨(dú)采用行程編碼,而是和其他編碼方法結(jié)合使用。例如,在JPEG中,就綜合使用了行程編碼、DCT、量化編碼以及哈夫曼編碼,先對(duì)圖像作分塊處理,再對(duì)這些分塊圖像進(jìn)行離散余弦變換(DCT),對(duì)變換后的頻域數(shù)據(jù)進(jìn)行量化并作Z字形掃描,接著對(duì)掃描結(jié)果作行程編碼,對(duì)行程編碼后的結(jié)果在作哈哈夫曼編碼。4.3.2行程編碼步驟PCX文件分為文件頭和圖像壓縮數(shù)據(jù)兩個(gè)部分。如果是256色圖像,則還有一個(gè)256色調(diào)色板存于文件尾部。文件頭全長(zhǎng)128字節(jié),包含了圖像的大小和顏色以及PCX文件的版本標(biāo)志等信息。其中頭信息的具體結(jié)構(gòu)為:typedefstruct{charmanufacturer;charversion;charencoding;charbits_per_pixel;WORDxmin,ymin;WORDxmax,ymax;WORDhres;WORDvres;charpalette[48];charreserved;charcolour_planes;WORDbytes_per_line;WORDpalette_type;charfiller[58]; }PCXHEAD;其中值得注意的是以下幾個(gè)數(shù)據(jù):manufacturer為PCX文件的標(biāo)志,必須為0x0a;xmin為最小的x坐標(biāo),xmax為最大的x坐標(biāo),所以圖像的寬度為xmax-xmin+1,同樣圖像的高度為ymax-ymin+1;bits_per_pixel為每個(gè)編碼行所占的字節(jié)數(shù)。圖像壓縮數(shù)據(jù)緊跟在文件頭后。如果沒(méi)有使用調(diào)色板,那么圖像壓縮數(shù)據(jù)存儲(chǔ)的是實(shí)際像素值;否則,存儲(chǔ)的是調(diào)色板的索引值。當(dāng)壓縮數(shù)據(jù)是實(shí)際的像素值時(shí),它們按顏色平面和掃描行存儲(chǔ),即每行先存儲(chǔ)所有R分量,再存儲(chǔ)所有G分量,最后存儲(chǔ)所有B分量,一行數(shù)據(jù)存儲(chǔ)完后,接著存儲(chǔ)下一行數(shù)據(jù)。如果使用了調(diào)色板,則不會(huì)分解為單獨(dú)的顏色平面存儲(chǔ)。下面以256色的PCX文件為例,說(shuō)明PCX文件中的行程編碼。256色PCX文件中,每個(gè)像素占一個(gè)字節(jié),壓縮數(shù)據(jù)以字節(jié)為單位逐行進(jìn)行編碼,每行填充到偶數(shù)字節(jié)。PCX文件規(guī)定編碼時(shí)的最大行程長(zhǎng)度為63,如果行程長(zhǎng)度大于63,則必須分多次存儲(chǔ)。對(duì)于長(zhǎng)度大于1的行程,編碼時(shí)先存入其行程長(zhǎng)度(長(zhǎng)度L加上192即0xC0),再存入該行程的代碼值,行程長(zhǎng)度和行程的代表值分別占一個(gè)字節(jié)。對(duì)于長(zhǎng)度為1的行程,即單個(gè)像素,如果該像素的值小于或等于0xC0,則編碼時(shí)直接存入該像素值,而不存儲(chǔ)長(zhǎng)度信息;否則,先存入0xC1,再存入該像素值,這樣做的目的是為了避免該像素值被誤認(rèn)為長(zhǎng)度信息。例如,連續(xù)100個(gè)灰度值為0x80的像素,其編碼(以十六進(jìn)制表示)應(yīng)為FF802580。上面的編碼中出現(xiàn)的FF的長(zhǎng)度信息是由63與0xC0相加所得。4.3.3行程編碼特點(diǎn)行程編碼比較適合于二值圖像(即圖像的各像素只有兩個(gè)值——黑或者白)的編碼,一般用于量化后出現(xiàn)大量零系數(shù)連續(xù)的場(chǎng)合,用行程來(lái)表示連零碼。如果圖像是由很多塊顏色或灰度相同的大面積區(qū)域組成的,那么采用行程編碼可以達(dá)到很高的壓縮比。如果圖像中的數(shù)據(jù)非常分散,則行程編碼不但不能壓縮數(shù)據(jù),反而會(huì)增加圖像文件的大小。極端情況如果圖像中每?jī)蓚€(gè)相鄰點(diǎn)的顏色都不同,用這種算法不但不能壓縮,反而數(shù)據(jù)量增加一倍。所以現(xiàn)在單純采用行程編碼的壓縮算法用得并不多,PCX文件算是其中的一種。五、實(shí)驗(yàn)內(nèi)容:5.1哈夫曼編碼5.1.1哈夫曼編碼算法實(shí)現(xiàn)資源文件HuffmanCoding.cpp中主要介紹哈夫曼編碼的算法,首先要從視圖類(lèi)CDImageProcessView中的OnHuffmancoding函數(shù)中得到0-255各灰度值出現(xiàn)的概率,在下面的算法中要基于這個(gè)概率值進(jìn)行哈夫曼編碼。首先要對(duì)這個(gè)概率值進(jìn)行從小到大的冒泡排序,然后從概率大于0處開(kāi)始編碼,灰度值較小的編為1,灰度值較大的編為0,再將最小的兩個(gè)灰度值相加,將加后的值與其他灰度值放在一起重新按從小到大排序,重復(fù)以上的步驟直到概率值相加為1。然后計(jì)算該圖像的熵值、平均碼字長(zhǎng)度及編碼效率。具體算法如下代碼所示:BOOLCHuffmanCoding::OnInitDialog(){//調(diào)用默認(rèn)的對(duì)話框初始化函數(shù) CDialog::OnInitDialog(); int i; //循環(huán)變量 int j; //循環(huán)變量 int k; //循環(huán)變量//圖像灰度出現(xiàn)概率中間結(jié)果的數(shù)組 double*temp; //數(shù)組用來(lái)存放灰度值和其位置之間的對(duì)應(yīng)關(guān)系 int * turn; //分配內(nèi)存 m_strCode=newCString[graygrade]; //分配內(nèi)存 turn=newint[graygrade]; //分配內(nèi)存 temp=newdouble[graygrade]; for(i=0;i<graygrade;i++) {//將grayfreq的值傳給temp temp[i]=grayfreq[i];//記錄灰度位置 turn[i]=i; } //中間變量 doublete; //用冒泡法對(duì)進(jìn)行灰度值出現(xiàn)的概率排序從小到大 //同時(shí)改變灰度值位置的映射關(guān)系 for(j=0;j<graygrade-1;j++) {for(i=0;i<graygrade-j-1;i++) {//如果前面的值大于后面的值 if(temp[i]>temp[i+1]) {//二者的值互換te=temp[i]; temp[i]=temp[i+1]; temp[i+1]=te;//將i和i+1灰度的位置值互換 for(k=0;k<graygrade;k++) { if(turn[k]==i) turn[k]=i+1; elseif(turn[k]==i+1) turn[k]=i; } } } } //從灰度概率大于0處開(kāi)始編碼 for(i=0;i<graygrade-1;i++) {if(temp[i]>0) break; } for(;i<graygrade-1;i++) {//更新m_strCode for(k=0;k<graygrade;k++) {//灰度值是否i if(turn[k]==i){//灰度值較小的碼字加1m_strCode[k]="1"+m_strCode[k];} elseif(turn[k]==i+1){//灰度值較大的碼字加0 m_strCode[k]="0"+m_strCode[k];} } //概率最小的兩個(gè)概率相加,保存在temp[i+1]中 temp[i+1]=temp[i]+temp[i+1];//改變映射關(guān)系 for(k=0;k<graygrade;k++) {//將位置為i的灰度值i改為灰度值i+1if(turn[k]==i) {turn[k]=i+1;} }//重新排序從i+1開(kāi)始 for(j=i+1;j<graygrade-1;j++) { if(temp[j]>temp[j+1]) { te=temp[j];//互換 temp[j]=temp[j+1]; temp[j+1]=te;//將i和i+1灰度的位置值互換 for(k=0;k<graygrade;k++) { if(turn[k]==j) turn[k]=j+1; elseif(turn[k]==j+1) turn[k]=j; } } else break;//退出循環(huán) } }//計(jì)算圖像熵 for(i=0;i<graygrade;i++) { if(grayfreq[i]>0){//計(jì)算圖像熵 m_shang-=grayfreq[i]*log(grayfreq[i])/log(2.0);} } //計(jì)算平均碼字長(zhǎng)度 for(i=0;i<graygrade;i++) { m_length+=grayfreq[i]*m_strCode[i].GetLength();//累加 }//計(jì)算編碼效率 m_effection=m_shang/m_length;//保存變動(dòng) UpdateData(FALSE);//字符串變量,列表項(xiàng)目的顯示 CString listname;//控件CodingList的ITEM LV_ITEMcodingItem;//保存控件ListCtrl中添加的ITEM編號(hào) int nItem2View; //設(shè)置CListCtrl控件樣式 m_codinglist.ModifyStyle(LVS_TYPEMASK,LVS_REPORT); //給List控件添加Header m_codinglist.InsertColumn(0,"像素灰度",LVCFMT_LEFT,70,0); m_codinglist.InsertColumn(1,"灰度概率",LVCFMT_LEFT,70,0); m_codinglist.InsertColumn(2,"編碼碼字",LVCFMT_LEFT,90,1); m_codinglist.InsertColumn(3,"碼字長(zhǎng)度",LVCFMT_LEFT,60,2);//設(shè)置樣式為文本 codingItem.mask=LVIF_TEXT;//添加顯示 for(i=0;i<graygrade;i++) {//第一列顯示 codingItem.iItem=m_codinglist.GetItemCount(); listname.Format("%u",i); codingItem.iSubItem=0;//顯示像素灰度 codingItem.pszText=(LPTSTR)(LPCTSTR)listname; nItem2View=m_codinglist.InsertItem(&codingItem); codingItem.iItem=nItem2View; //第二列顯示 codingItem.iSubItem=1; listname.Format("%f",grayfreq[i]); codingItem.pszText=(LPTSTR)(LPCTSTR)listname; m_codinglist.SetItem(&codingItem); //第三列顯示 codingItem.iSubItem=2; codingItem.pszText=(LPTSTR)(LPCTSTR)m_strCode[i]; m_codinglist.SetItem(&codingItem); //第四列顯示 codingItem.iSubItem=3; listname.Format("%u",m_strCode[i].GetLength()); codingItem.pszText=(LPTSTR)(LPCTSTR)listname; m_codinglist.SetItem(&codingItem); } deleteturn;//內(nèi)存釋放 deletetemp; returnTRUE;//返回TRUE}5.1.2視圖類(lèi)OnHuffmancoding()函數(shù)此函數(shù)是用來(lái)統(tǒng)計(jì)各灰度值出現(xiàn)的概率,并以對(duì)話框的形式顯示通過(guò)算法計(jì)算出的結(jié)論值。首先是通過(guò)CDib類(lèi)中的GetBits()函數(shù)來(lái)獲取圖像像素的起始位置,因?yàn)楸境绦蛑恢С?56色的位圖圖像,所以要進(jìn)行判斷(如果不是256色的位圖圖像則彈出對(duì)話框提示“只支持256色位圖圖像”)。然后通過(guò)CDib類(lèi)中的GetWidth()和GetHeight()函數(shù)返回圖像的寬度和高度,用于計(jì)算圖像的像素總和及控制循環(huán)邊界。用兩個(gè)for的嵌套循環(huán)對(duì)圖像的進(jìn)行逐行掃描,以統(tǒng)計(jì)出每個(gè)灰度值出現(xiàn)的次數(shù),再除以像素總和就可以得到每個(gè)灰度值的概率,此概率要參與到哈夫曼編碼算法中。最后要顯示出哈夫曼編碼的結(jié)果,本程序是通過(guò)對(duì)話框來(lái)顯示的。voidCDImageProcessView::OnHuffmancoding(){//獲取文檔 CDImageProcessDoc*pDoc=GetDocument();//指向源圖像的指針 unsignedchar* lpSrc; //指向DIB的指針 LPSTRlpDIB; //指向DIB象素指針 LPSTRlpDIBBits;//圖像灰度等級(jí)數(shù) intgraygrade;//鎖定DIB lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHObject());//找到DIB圖像象素起始位置 lpDIBBits=pDoc->m_dib.GetBits(lpDIB); //判斷是否是8-bpp位圖 if(pDoc->m_dib.GetColorNum(lpDIB)!=256) {//提示用戶 MessageBox("目前只支持256色位圖!","系統(tǒng)提示", MB_ICONINFORMATION|MB_OK); //解除鎖定 ::GlobalUnlock((HGLOBAL)pDoc->GetHObject()); return;//返回 }//灰度等級(jí)數(shù)為256 graygrade=pDoc->m_dib.GetColorNum(lpDIB);//各灰度等級(jí)出現(xiàn)的概率 double*grayfreq;//圖像寬度 intwidth;//圖像高度 intheight; width=pDoc->m_dib.GetWidth(lpDIB); height=pDoc->m_dib.GetHeight(lpDIB);//更改光標(biāo)形狀 BeginWaitCursor();//分配內(nèi)存 grayfreq=newdouble[graygrade];//像素?cái)?shù)目 intgraySum; inti; intj; graySum=width*height; //計(jì)算圖象象素總數(shù) for(i=0;i<graygrade;i++) {//賦零值grayfreq[i]=0.0; }//計(jì)算各個(gè)灰度值的計(jì)數(shù) for(i=0;i<height;i++) { for(j=0;j<width;j++) {//指向圖象指針 lpSrc=(unsignedchar*)lpDIBBits+width*i+j;//相應(yīng)的灰度計(jì)數(shù)加1 grayfreq[*(lpSrc)]=grayfreq[*(lpSrc)]+1; } }//計(jì)算各個(gè)灰度值出現(xiàn)的概率 for(i=0;i<graygrade;i++) { grayfreq[i]=grayfreq[i]/(double)graySum; } //構(gòu)建霍夫曼編碼的碼表,并用對(duì)話框顯示霍夫曼碼表 CHuffmanCodingcoding; //創(chuàng)建對(duì)話框 coding.grayfreq=grayfreq;//初始化變量值 coding.graygrade=graygrade; coding.DoModal(); //顯示對(duì)話框 EndWaitCursor(); //恢復(fù)光標(biāo)5.2香農(nóng)-范諾編碼5.2.1香農(nóng)-范諾編碼算法實(shí)現(xiàn)資源文件ShannonCoding.cpp是香農(nóng)-范諾編碼的算法程序。與哈夫曼算法相似地從視圖類(lèi)中得到每個(gè)灰度值出現(xiàn)的概率,針對(duì)這個(gè)概率進(jìn)行編碼。首先用冒泡法從小到大對(duì)概率進(jìn)行排序,從概率大于0處開(kāi)始進(jìn)行編碼,對(duì)概率區(qū)間進(jìn)行分割,然后對(duì)每個(gè)灰度值對(duì)應(yīng)的編碼數(shù)組進(jìn)行追加字符,初始時(shí)追加為1,當(dāng)超出概率總和的一半時(shí),追加的字符改為0,接著繼續(xù)對(duì)上半部分的區(qū)間進(jìn)行分割,此時(shí)概率的總和就改為上半部分的概率總和了,重復(fù)上述操作,完成整幅圖像的編碼。具體代碼如下所示:BOOLCShannonCoding::OnInitDialog(){//調(diào)用默認(rèn)得OnInitDialog()函數(shù) CDialog::OnInitDialog();//字符串變量 CString str; str="1"; int i; int j; //圖像灰度出現(xiàn)概率中間結(jié)果的數(shù)組 double* temp;//數(shù)組用來(lái)存放灰度值和其位置之間 int * turn; temp=newdouble[graygrade]; //數(shù)組用來(lái)存放灰度值和其位置之間的映射 turn=newint[graygrade];//臨時(shí)變量 int temp2;//當(dāng)前編碼區(qū)間的概率和 double effectcum;//初始的概率和為1.0 effectcum=1.0; //已經(jīng)編碼灰度值概率的統(tǒng)計(jì)和 double dSum;//初始化為0 dSum=0; //已編碼灰度值 int lCount=0; //起始位置 int lBegin;//指示編碼是否已經(jīng)完成一段 BOOL *bFinished; bFinished=newBOOL[graygrade];//分配內(nèi)存 m_strCode=newCString[graygrade]; for(i=0;i<graygrade;i++) { //初始化為FALSE bFinished[i]=FALSE; //將概率賦值temp數(shù)組 temp[i]=grayfreq[i];//按灰度值大小順序排列 turn[i]=i; }//中間變量 double te;//用冒泡法對(duì)進(jìn)行灰度值出現(xiàn)的概率排序 //同時(shí)改變灰度值位置的映射關(guān)系 for(j=0;j<graygrade-1;j++) { for(i=0;i<graygrade-j-1;i++) { if(temp[i]>temp[i+1]) {//互換 te=temp[i]; temp[i]=temp[i+1]; temp[i+1]=te; //將i和i+1灰度的位置值互換 temp2=turn[i]; turn[i]=turn[i+1]; turn[i+1]=temp2; } } } //計(jì)算香農(nóng)-弗諾編碼表,從概率大于0處開(kāi)始編碼 for(lBegin=0;lBegin<graygrade-1;lBegin++) { if(temp[lBegin]>0) {break; } } //開(kāi)始編碼 while(lCount<graygrade) {//從概率大于零的灰度值開(kāi)始編碼 lCount=lBegin; //對(duì)區(qū)間進(jìn)行分割,對(duì)每個(gè)區(qū)間的灰度值編碼 for(i=lBegin;i<graygrade;i++) {//判斷是否編碼完成 if(bFinished[i]==FALSE) {//增加當(dāng)前編碼區(qū)間的概率綜合 dSum+=temp[i];//判斷是否超出總和的一半 if(dSum>effectcum/2.0) {//超出,追加的字符改為0 str="0"; }//追加字符 m_strCode[turn[i]]=m_strCode[turn[i]]+str;//判斷是否編碼完一段 if(dSum==effectcum) {//完成一部分編碼,重新計(jì)算effectcum dSum=0;//初始化dSum為0//判斷是不是對(duì)所有灰度值已經(jīng)編碼一遍 if(i==graygrade-1) {j=lBegin;} else {j=i+1;} temp2=j;//保存j值 str=m_strCode[turn[j]]; //計(jì)算下一編碼區(qū)間的概率總和 effectcum=0; for(;j<graygrade;j++) {//判斷是否是同一段編碼 if((m_strCode[turn[j]].Right(1)!=str.Right(1)) ||(m_strCode[turn[j]].GetLength()!=str.GetLength())) break;//當(dāng)前區(qū)間的概率總和增加 effectcum+=temp[j]; }//碼字增加值為1 str="1"; //判斷該段編碼已經(jīng)完成 if(temp2+1==j) { bFinished[temp2]=TRUE;} } } else {//開(kāi)始下一輪編碼 lCount++;//重新賦dSum為0 dSum=0;//判斷是不是對(duì)所有灰度值已經(jīng)編碼一遍 if(i==graygrade-1) { j=lBegin;} else {j=i+1;} temp2=j;//保存j值 str=m_strCode[turn[j]]; //計(jì)算下一編碼區(qū)間的概率總和 effectcum=0; for(;j<graygrade;j++) {//判斷是否是同一段編碼 if((m_strCode[turn[j]].Right(1)!=str.Right(1)) ||(m_strCode[turn[j]].GetLength()!=str.GetLength())) {//退出循環(huán)break; } effectcum+=temp[j];//累加 } str="1";//判斷該段編碼已經(jīng)完成 if(temp2+1==j) bFinished[temp2]=TRUE; } } }//計(jì)算圖像熵 for(i=0;i<graygrade;i++) {//判斷概率是否大于0 if(grayfreq[i]>0) {//計(jì)算圖像熵 m_shang-=grayfreq[i]*log(grayfreq[i])/log(2.0); } }//計(jì)算平均碼字長(zhǎng)度 for(i=0;i<graygrade;i++) {//累加 m_length+=grayfreq[i]*m_strCode[i].GetLength(); }//計(jì)算編碼效率 m_effect=m_shang/m_length; //保存變動(dòng) UpdateData(FALSE); //輸出編碼結(jié)果 //字符串變量,列表項(xiàng)目的顯示 CString listname;//控件ListCtrl的ITEM LV_ITEMcodingItem;//保存控件ListCtrl中添加的ITEM編號(hào) int nItem2View; //設(shè)置CListCtrl控件樣式 m_codinglist.ModifyStyle(LVS_TYPEMASK,LVS_REPORT); //給List控件添加Header m_codinglist.InsertColumn(0,"像素灰度",LVCFMT_LEFT,70,0); m_codinglist.InsertColumn(1,"灰度概率",LVCFMT_LEFT,70,0); m_codinglist.InsertColumn(2,"編碼碼字",LVCFMT_LEFT,90,1); m_codinglist.InsertColumn(3,"碼字長(zhǎng)度",LVCFMT_LEFT,60,2); //設(shè)置樣式為文本 codingItem.mask=LVIF_TEXT;//添加顯示 for(i=0;i<graygrade;i++) {//第一列顯示 codingItem.iItem=m_codinglist.GetItemCount(); listname.Format("%u",i); codingItem.iSubItem=0;//顯示像素灰度 codingItem.pszText=(LPTSTR)(LPCTSTR)listname; nItem2View=m_codinglist.InsertItem(&codingItem); codingItem.iItem=nItem2View; //第二列顯示 codingItem.iSubItem=1; listname.Format("%f",grayfreq[i]); codingItem.pszText=(LPTSTR)(LPCTSTR)listname; m_codinglist.SetItem(&codingItem);//第三列顯示 codingItem.iSubItem=2; codingItem.pszText=(LPTSTR)(LPCTSTR)m_strCode[i]; m_codinglist.SetItem(&codingItem);//第四列顯示 codingItem.iSubItem=3; listname.Format("%u",m_strCode[i].GetLength()); codingItem.pszText=(LPTSTR)(LPCTSTR)listname; m_codinglist.SetItem(&codingItem); } deleteturn;//內(nèi)存釋放 deletetemp; deletebFinished; returnTRUE;}5.2.2視圖類(lèi)處理函數(shù)OnShannonCoding()函數(shù)關(guān)于函數(shù)的調(diào)用部分,在圖像處理的主窗口的菜單欄“圖像編碼”下添加“香農(nóng)-范諾編碼”項(xiàng),對(duì)應(yīng)的處理函數(shù)是CDImageProcessView視圖類(lèi)中的OnShannoncoding()函數(shù)。OnShannoncoding()函數(shù)實(shí)現(xiàn)了圖像灰度概率的計(jì)算和編碼對(duì)話框的調(diào)用,具體代碼如下:voidCDImageProcessView::OnShannoncoding(){//獲取文檔 CDImageProcessDoc*pDoc=GetDocument();//指向源圖像的指針 unsignedchar* lpSrc; //指向DIB的指針 LPSTRlpDIB; //指向DIB象素指針 LPSTRlpDIBBits;//圖像灰度等級(jí)數(shù) intgraygrade;//鎖定DIB lpDIB=(LPSTR)::GlobalLock((HGLOBAL)pDoc->GetHObject());//找到DIB圖像象素起始位置 lpDIBBits=pDoc->m_dib.GetBits(lpDIB); //判斷是否是8位位圖 if(pDoc->m_dib.GetColorNum(lpDIB)!=256) {//提示用戶 MessageBox("目前只支持256色位圖!","系統(tǒng)提示", MB_ICONINFORMATION|MB_OK); ::GlobalUnlock((HGLOBAL)pDoc->GetHObject());//解除鎖定 return;//返回 }//灰度等級(jí)數(shù)為256 graygrade=pDoc->m_dib.GetColorNum(lpDIB);//各灰度等級(jí)出現(xiàn)的概率 double*grayfreq;//圖像寬度 intwidth;//圖像高度 intheight; width=pDoc->m_dib.GetWidth(lpDIB); height=pDoc->m_dib.GetHeight(lpDIB);//更改光標(biāo)形狀 BeginWaitCursor(); //開(kāi)始計(jì)算各個(gè)灰度級(jí)出現(xiàn)的概率,如果需要對(duì)指定的序列進(jìn)行哈夫曼編碼, //只要將這一步改成給各個(gè)灰度級(jí)概率賦值即可 grayfreq=newdouble[graygrade];//分配內(nèi)存 intgraySum;//像素?cái)?shù)目 inti;//循環(huán)變量 intj;//循環(huán)變量//計(jì)算圖象象素總數(shù) graySum=width*height; for(i=0;i<graygrade;i++) {//賦零值 grayfreq[i]=0.0; }//計(jì)算各個(gè)灰度值的計(jì)數(shù) for(i=0;i<height;i++) { for(j=0;j<width;j++) {//指向圖象指針 lpSrc=(unsignedchar*)lpDIBBits+width*i+j;//相應(yīng)的灰度計(jì)數(shù)加1 grayfreq[*(lpSrc)]=grayfreq[*(lpSrc)]+1; } } for(i=0;i<graygrade;i++) {//計(jì)算各個(gè)灰度值出現(xiàn)的概率 grayfreq[i]=grayfreq[i]/(double)graySum; } CShannonCodingcoding;//創(chuàng)建對(duì)話框 coding.grayfreq=grayfreq;//初始化變量值 coding.graygrade=graygrade; coding.DoModal(); //顯示對(duì)話框 EndWaitCursor(); //恢復(fù)光標(biāo)}5.3行程編碼5.3.1行程編碼算法實(shí)現(xiàn)函數(shù)PCXCoding()將指定的256色DIB對(duì)象保存為256色PCX文件。參數(shù)LPSTRlpDIBBits是指向DIB對(duì)象像素的指針;參數(shù)LONGImageWidth是源圖像寬度(像素?cái)?shù),必須是4的倍數(shù));參數(shù)LONGImageHeight是源圖像高度(像素?cái)?shù));參數(shù)CFile&file是要保存的文件。BOOLPCXCoding(LPSTRlpDIBBits,LONGImageWidth,LONGImageHeight,CFile&file){ typedefstruct{ charmanufacturer; charversion; charencoding; charbits_per_pixel; WORDxmin,ymin; WORDxmax,ymax; WORDhres; WORDvres; charpalette[48]; charreserved; charcolour_planes; WORDbytes_per_line; WORDpalette_type; charfiller[58]; }PCXHEAD;inti;intj;//中間變量BYTEbChar1;//中間變量BYTEbChar2;//指向源圖像像素的指針BYTE*lpSrc;//指向編碼后圖像數(shù)據(jù)的指針BYTE*lpDst;//重復(fù)像素計(jì)數(shù)intiCount;//緩沖區(qū)已使用的字節(jié)數(shù)DWORDdwBuffUsed;//PCX文件頭PCXHEADpcxHeadr;//PCX標(biāo)志碼pcxHeadr.manufacturer=0x0A;//PCX版本號(hào)pcxHeadr.version=5;//PCX編碼方式(1表示RLE編碼)pcxHeadr.encoding=1;//像素位數(shù)(256色為8位)pcxHeadr.bits_per_pixel=8;//圖像相對(duì)于屏幕的左上角X坐標(biāo)pcxHeadr.xmin=0;//圖像相對(duì)于屏幕的左上角Y坐標(biāo)pcxHeadr.ymin=0;//圖像相對(duì)于屏幕的右下角X坐標(biāo)pcxHeadr.xmax=ImageWidth-1;//圖像相對(duì)于屏幕的右下角Y坐標(biāo)pcxHeadr.ymax=ImageHeight-1;//圖像的水平分辨率pcxHeadr.hres=ImageWidth;//圖像的垂直分辨率pcxHeadr.vres=ImageHeight;for(i=0;i<48;i++){//調(diào)色板數(shù)據(jù)(對(duì)于256色PCX無(wú)意義,直接賦值為0) pcxHeadr.palette[i]=0;}//保留域設(shè)定為0pcxHeadr.reserved=0;//圖像色彩平面數(shù)目對(duì)于256色PCX設(shè)為1pcxHeadr.colour_planes=1;//圖像的寬度(字節(jié)為單位)必須為偶數(shù)pcxHeadr.bytes_per_line=ImageWidth;//圖像調(diào)色板的類(lèi)型,1表示彩色或者單色圖像,2表示圖像是灰度圖pcxHeadr.palette_type=1;for(i=0;i<54;i++){ pcxHeadr.filler[i]=0;}//寫(xiě)入頭文件file.Write((LPSTR)&pcxHeadr,sizeof(PCXHEAD));//分配內(nèi)存以保存編碼結(jié)果lpDst=newBYTE[ImageHeight*ImageWidth*2];//指明當(dāng)前已經(jīng)用了多少緩沖區(qū)(字節(jié)數(shù))dwBuffUsed=0;for(i=0;i<ImageHeight;i++){//指向DIB第i行,第0個(gè)像素的指針 lpSrc=(BYTE*)lpDIBBits+ImageWidth*(ImageHeight-1-i);//給bChar1賦值 bChar1=*lpSrc;//設(shè)置iCount為1iCount=1; for(j=1;j<ImageWidth;j++) { lpSrc++; bChar2=*lpSrc; if((bChar1==bChar2)&&(iCount<63)) iCount++; else { if((iCount>1)||(bChar1>=0xC0)) { lpDst[dwBuffUsed]=iCount|0xC0; lpDst[dwBuffUsed+1]=bChar1; dwBuffUsed+=2; } else { lpDst[dwBuffUsed]=bChar1; dwBuffUsed++; } bChar1=bChar2; iCount=1; } } if((iCount>1)||(bChar1>=0xC0)) { lpDst[dwBuffUsed]=iCount|0xC0; lpDst[dwBuffUsed+1]=bChar1; dwBuffUsed+=2; } else { lpDst[dwBuffUsed]=bChar1; dwBuffUsed++; }}file.WriteHuge((LPSTR)lpDst,dwBuffUsed);delete[]lpDst;lpDst=newBYTE[769];*lpDst=0x0C;for(i=0;i<256;i++){ lpDst[i*3+1]=i;lpDst[i*3+2]=i; lpDst[i*3+3]=i;}file.Write((LPSTR)lpDst,769);returnTRUE;}5.3.2視圖類(lèi)處理函數(shù)OnRleCoding()關(guān)于PCXCoding的函數(shù)調(diào)用部分,在圖像處理的主窗口菜單欄“圖像編碼”下添加“行程編碼”項(xiàng),對(duì)應(yīng)的處理函數(shù)是CDImageProces
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度年福建省高校教師資格證之高等教育心理學(xué)通關(guān)試題庫(kù)(有答案)
- 2024年熟食制品項(xiàng)目資金籌措計(jì)劃書(shū)代可行性研究報(bào)告
- 2024年造紙完成工段智能裝備項(xiàng)目資金申請(qǐng)報(bào)告代可行性研究報(bào)告
- 2024常年采購(gòu)協(xié)議條款與條件示例
- 2024年度建材銷(xiāo)售協(xié)議格式
- 2024年專(zhuān)業(yè)門(mén)窗安裝服務(wù)協(xié)議模板
- 2024公司B棟生產(chǎn)車(chē)間租賃協(xié)議
- 員工基本行為準(zhǔn)則
- 銀行外匯便利化政策落實(shí)情況總結(jié)
- 2024年規(guī)范二手公寓房產(chǎn)交易協(xié)議書(shū)
- 微型計(jì)算機(jī)原理與應(yīng)用習(xí)題集及答案
- 河北省唐山市藥品零售藥店企業(yè)藥房名單目錄
- 喵喵老師制作 電子百拼的黑白電路圖
- DB34-T 4010-2021 水利工程外觀質(zhì)量評(píng)定規(guī)程-高清現(xiàn)行
- 《整改報(bào)告》模板
- 送達(dá)地址確認(rèn)書(shū)(樣本)
- 江蘇省歷屆中學(xué)生與社會(huì)作文大賽決賽試題及獲獎(jiǎng)范文(完整版)資料
- 六年級(jí)數(shù)學(xué)上冊(cè)教案-分?jǐn)?shù)乘法整理與練習(xí) 蘇教版
- 《民航服務(wù)禮儀》項(xiàng)目五 地面服務(wù)禮儀
- 營(yíng)業(yè)執(zhí)照借用免責(zé)協(xié)議
- 小學(xué)道德與法治人教三年級(jí)上冊(cè)第三單元安全護(hù)我成長(zhǎng)-《遭遇陌生人》教案
評(píng)論
0/150
提交評(píng)論