幾個(gè)圖像縮放算法的比較
前段時(shí)間由于項(xiàng)目的需求,需要實(shí)現(xiàn)圖像的縮放功能,期間查找了不少關(guān)于圖像縮放算法的資料,現(xiàn)把自己的心得整理一下。
由于研究生期間沒(méi)有選修過(guò)圖像處理方面的課程,所以對(duì)圖像縮放的原理可謂一竅不通,當(dāng)時(shí)開(kāi)始編寫(xiě)代碼的時(shí)候簡(jiǎn)直就是一頭霧水。而且網(wǎng)上雖然介紹圖像處理的代碼很多,但涉及圖像縮放的代碼卻很少,因?yàn)楹芏嘬浖贾苯邮褂昧藈indows的GDI函數(shù)庫(kù)的API函數(shù):StretchBlt,或者VCL中TCanvas類(lèi)的StretchDraw。無(wú)奈這兩個(gè)函數(shù)都是直接對(duì)BMP圖像進(jìn)行縮放,而且StretchBlt是在CDC里面調(diào)用的,結(jié)果只是在顯示的時(shí)候?qū)D像進(jìn)行縮放,不能夠進(jìn)行縮放的存儲(chǔ)。那些天在GDI和GDIPLUS摸索了半天,都找不到合適的函數(shù),某天卻迸出個(gè)想法來(lái):圖像放大不就是把每個(gè)象素點(diǎn)再多弄幾個(gè)出來(lái),而縮小不就是去掉里面一些象素點(diǎn)。所以就按照自己的想法寫(xiě)了一個(gè)比較粗糙的放大函數(shù):
BYTE *src,*dst,*ptr,*buffer,*next;
for(int i=0,n=0; i < this->Height(); i++,n=n+rate)
{
src = this->GetLinePtr(i);
dst = tempdib->GetLinePtr(n);
ptr = dst;
for(int j=0; j < this->Width(); j++,ptr=ptr+3*rate)
{
memcpy(ptr,src+j*3,3);
for(int m=1;m
memcpy(ptr+m*3,ptr,3);
}
for(int m=n+1;m
{
buffer = dst;
next = tempdib->GetLinePtr(m);
ptr = next;
memcpy(ptr,buffer,dstwidth*3);
}
}
這段代碼的效果比較粗糙,但處理的辦法比較有意思。首先是讀取一行的圖像數(shù)據(jù),然后在每一行循環(huán)讀取一個(gè)象素的RGB值并復(fù)制到新圖像的內(nèi)存空間,然后根據(jù)放大的比例再作一次循環(huán),把這個(gè)RGB值按照比例復(fù)制進(jìn)內(nèi)存空間。當(dāng)進(jìn)行完一行的處理后,在新圖像的內(nèi)存空間進(jìn)行一次循環(huán)處理,把這行數(shù)據(jù)按照比例復(fù)制給下面幾行。這樣就通過(guò)象素點(diǎn)的復(fù)制實(shí)現(xiàn)了圖片的放大。不過(guò)放大的效果不是特別好,圖像列方向上會(huì)出現(xiàn)很多的毛刺,放大4倍的話圖像就很模糊了。
所以還是重新去查找資料,結(jié)果在網(wǎng)上搜到一篇不錯(cuò)的文章——用線性插值算法實(shí)現(xiàn)圖像縮放。看了文章,才發(fā)現(xiàn)我原先的辦法還真不是一般的原始,不過(guò)思路還跟GDI里面的StretchBlt差不多。StretchBlt采用的方法在圖像處理領(lǐng)域稱為最近鄰域法,其基本原理就是先取出原圖的相鄰四個(gè)點(diǎn),然后把新位置的點(diǎn)跟這四個(gè)點(diǎn)的位置做比較,把最近一個(gè)點(diǎn)的RGB值賦給新位置的點(diǎn)。所以在放大的時(shí)候,幾乎就是像我那樣把前一個(gè)點(diǎn)的象素賦給新位置的點(diǎn)。這樣處理的結(jié)果就是導(dǎo)致圖像不夠平滑,因?yàn)辄c(diǎn)與點(diǎn)之間是一個(gè)過(guò)渡的過(guò)程,不是簡(jiǎn)單的復(fù)制,稍微好點(diǎn)的辦法就是把新點(diǎn)附近幾個(gè)點(diǎn)的顏色值取平均再賦給這個(gè)點(diǎn)。這種方法在數(shù)值計(jì)算方法叫做線性插值。但那篇文章提供了一個(gè)更好的方法,叫做二維線性插值,其原理也是對(duì)附近的點(diǎn)取平均,但它對(duì)各個(gè)點(diǎn)的顏色值加上不同的權(quán)數(shù),這個(gè)權(quán)數(shù)就是各個(gè)點(diǎn)距離這個(gè)點(diǎn)的位置。其計(jì)算方法如下:
P = n*b*PA + n * ( 1 – b )*PB + ( 1 – n ) * b * PC + ( 1 – n ) * ( 1 – b ) * PD
其中:n為v(映射后相應(yīng)點(diǎn)在源圖像中的Y軸坐標(biāo),一般不是整數(shù))下面最接
|
|