影像處理-內插法應用於圖片縮放 |
|
JerryKuo
版主 發表:42 回覆:571 積分:322 註冊:2003-03-10 發送簡訊給我 |
在影像處理中,例如:縮放(zoom)、改變大小(Resize)、補償(compensation)
常常會參考原圖,做取樣(sampling)的動作,就以縮小為例。為了將原圖縮小,
一般做法會以n點(pixel)取一點的方式取樣,長寬是原來的1/n所得到的圖面
積剛好是原來的 (1/n x 1/n)=1/(n^2)。為整數平方分之一倍。 如果縮小倍率不是整數平方,而是2倍、3倍,則取樣的位置將不一定都是
整數位置,座標涵有小數值。一般都不會考慮這小數值,直接取其整數值座標
取樣,也就是(2.3, 3.6)四捨五入取整數值,取樣值就是座標(2,4)的像素。
在一張像素都很相近(smooth)的圖,這樣取樣的方式,所造成的失真並不會
很嚴重。如果在一張顏色變化大的圖中取樣,所造成的失真值將為數可觀。
因為(2.3,3.6)座標的像素實際顏色,並不一定就(2,4)顏色,(2,3),(3,3)或(3,4)
的顏色,如果選錯了,黑的變成白的,就會照成很大的失真。
在為了怕選錯的兩難之際,我們可以用bilinear方法,求得介於相鄰四點形
成的bilinear曲面公式,代入非整數座標的可得像素值。bilinear公式有很多
種。我就不列舉,因為用不到,原因是參數很難解,計算複雜度很高。所以我們
簡化為內插法,以近似bilinear公式,誤差dy。
內插法是利用相鄰四點的像素值,依照已知的非整數座標相鄰距離的遠近,根
據比例求得取樣值。也就是接近哪個點就像那個點。距離近的取樣比例大,距
離遠的取樣比例小。 內插公式如下:
clr(x,y) = (1-fx)*(1-fy)*clr1 + fx *(1-fy)*clr2 + (1-fx)* fy *clr3 + fx * fy *clr4非整數座標(x,y),顏色為clr(x,y),小數值為(fx,fy),整數值(Ix,Iy) 相鄰四點座標(Ix,Iy), (Ix+1,Iy), (Ix,Iy+1), (Ix+1,Iy+1) 顏色分別為 clr1 , clr2 , clr3 , clr4 可參考下圖 在縮放圖片時運用內插法處理,如此可以求得較好的取樣。 理論上,使用內插法求得縮放大小的圖片,相鄰像素之間會比直接取整數點更 有連續性,也就是更smooth。所以使用內插法取樣時,個人覺得除了取樣之外, 同時也做了低通濾波,處理後的圖片可再做一次銳化,使圖片更清晰。 附帶一提,當fx,fy固定在0.5時, 在mpeg壓縮中稱之為half-pixel, 使用half-pixel 運動估測所得到的PSNR可以提升約0.5dB, 相當可觀。只是相對的,處理速度相 對的變慢了一點。 附加檔案是圖片縮放程式使用內插法,我是直接用RGB去做內插法,其實應該先轉 YUV處理之後,再轉回RGB比較適當。給大家參考指教。
附加檔案:34732_Bilinear.zip
|
qalin
一般會員 發表:20 回覆:45 積分:13 註冊:2003-07-18 發送簡訊給我 |
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
長官
下列是我之前寫的程式部分片段
(函式傳入參數 select_type 只是決定轉檔 size ,不要理它)
程式碼是我抄來並改寫的
不過我發覺內插法轉出圖片效果較差(經果肉眼仔細比對照片)
後來改成直接用 Windows API 轉 ...(看 Source Code)
不知我 Source Code (被 mark 掉的部分)
用的是否真的是內差法 ?? (我數學不好)
3Q
//--------------------------------------------------------------------------- void __fastcall TForm1::ChangeJpgSize(String FileName , int select_type) //內差法 (for jpg) { TJPEGImage *jpg = new TJPEGImage(); Graphics::TBitmap *bmp1 = new Graphics::TBitmap(); Graphics::TBitmap *bmp2 = new Graphics::TBitmap(); jpg->LoadFromFile(FileName); bmp1->Assign(jpg); //欲改變的 Size if (select_type==0) //320 X 240 { bmp2->Width=320; bmp2->Height=240; } else { bmp2->Width=640; bmp2->Height=480; } /* //內差法效果較差 int x1,y1,x2,y2,x0,y0,dx,dy,x,y; x1=bmp1->Width; y1=bmp1->Height; x2=bmp2->Width; y2=bmp2->Height; dx=0; x0=0; for (x=0 ; x<=bmp2->Width-1 ; x ) { dy=0; y0=0; dx=dx x1; while (dx>=x2) { x0 ; dx=dx-x2; } for (y=0 ; y<=bmp2->Height-1 ; y ) { dy=dy y1; while (dy>=y2) { y0 ; dy=dy-y2; } bmp2->Canvas->Pixels[x][y]=bmp1->Canvas->Pixels[x0][y0]; } } jpg->Assign(bmp2); */ bmp2->PixelFormat = jf24Bit; SetStretchBltMode(bmp2->Canvas->Handle, COLORONCOLOR); StretchBlt(bmp2->Canvas->Handle,0,0,bmp2->Width,bmp2->Height, bmp1->Canvas->Handle,0,0,bmp1->Width,bmp1->Height,SRCCOPY); jpg->Assign(bmp2); String DestDir; if (select_type==0) //320 X 240 { DestDir="c:\\320X240\\"; if (!DirectoryExists(DestDir)) ForceDirectories(DestDir); } else { DestDir="c:\\640x480\\"; if (!DirectoryExists(DestDir)) ForceDirectories(DestDir); } jpg->SaveToFile(DestDir ExtractFileName(FileName)); delete jpg; delete bmp1; delete bmp2; } |
JerryKuo
版主 發表:42 回覆:571 積分:322 註冊:2003-03-10 發送簡訊給我 |
引言:內插法最簡單的意思就是與相鄰的點相關連,所以需要相鄰的四點做內插,由紅字 部分來看,只用到一個像素對映,這樣的方法只能稱為nearest neighborhood, 另外,將圖由320x240放大到640x480,是整數放大,用nearest neighborhood放大 後,雖然會有馬賽克的現象,不過效果應該也是相當不錯的。 小弟並沒有看完你所附的程式,只是從紅字那一行,很容易知道是不是內插法, 你的方法很可能是nearest neighborhood。我猜啦//內差法效果較差 int x1,y1,x2,y2,x0,y0,dx,dy,x,y; x1=bmp1->Width; y1=bmp1->Height; x2=bmp2->Width; y2=bmp2->Height; dx=0; x0=0; for (x=0 ; x<=bmp2->Width-1 ; x ) { dy=0; y0=0; dx=dx x1; while (dx>=x2) { x0 ; dx=dx-x2; } for (y=0 ; y<=bmp2->Height-1 ; y ) { dy=dy y1; while (dy>=y2) { y0 ; dy=dy-y2; } bmp2->Canvas->Pixels[x][y]=bmp1->Canvas->Pixels[x0][y0]; } } jpg->Assign(bmp2); |
happosai
高階會員 發表:93 回覆:228 積分:109 註冊:2002-09-15 發送簡訊給我 |
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
經過測試,以及比較下面兩篇文章的內容
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=23589
http://delphi.ktop.com.tw/topic.php?topic_id=43046 剛才做出的測試報告
1.我之前的程式碼中內插法是從站長範例程式抄出來的
2.站長的程式中提供所謂的內插法及平滑法
3.之前測試站長的內插法(JerryKuo 長官說可能是 nearest neighborhood 法)效果較API法差
4.但 JerryKuo 長官提供的 內插法又較 API 法效果好
5.之前沒測試站長的平滑法,今天一起測試發現平滑法跟JerryKuo 長官提供的 內插法效果不分軒輊(可能要多取樣不同的照片才能最後定論)
6.目前總結:由優而列->
JerryKuo 長官內插法跟站長平滑法差不多 > API 法 > 站長內插法 但站長平滑法是所有轉出圖檔中 Size 最小的
所以應該是目前測試出最完美的轉檔方法,但得再多找幾張圖片測試 我的測試程式已放於
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=43205 發表人 - bruce0211 於 2004/01/06 17:41:52
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
引言: Dr. Dobb's Journal 2002, May 有一篇文章非常不錯,也是在講影像縮放 http://www.ddj.com/articles/2002/0205/ Image Scaling With Bresenham 這個演算法是由 Bresenham Line-Drawing Algorithm 延伸而來, 沒有使用乘法跟除法,速度非常快,但是仍能有不錯的品質...:)長官,該網站需要註冊 是否可以直接 mail 範例 source code 給我測試,謝謝 |
happosai
高階會員 發表:93 回覆:228 積分:109 註冊:2002-09-15 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |