全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:14672
推到 Plurk!
推到 Facebook!

影像處理-內插法應用於圖片縮放

 
JerryKuo
版主


發表:42
回覆:571
積分:322
註冊:2003-03-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-07-28 12:38:25 IP:61.230.xxx.xxx 未訂閱
在影像處理中,例如:縮放(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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-01-02 21:09:42 IP:218.90.xxx.xxx 未訂閱
哇,非常好!可惜我沒裝BCB,不知斑竹有無DELHPI版本的CODE?不然我只好找個BCB來裝了,呵呵! 謝謝斑竹的好作品!
bruce0211
版主


發表:157
回覆:668
積分:279
註冊:2002-06-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-01-06 08:56:22 IP:211.21.xxx.xxx 未訂閱
長官 下列是我之前寫的程式部分片段 (函式傳入參數 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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-01-06 09:57:12 IP:61.230.xxx.xxx 未訂閱
引言:
  //內差法效果較差
  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);
內插法最簡單的意思就是與相鄰的點相關連,所以需要相鄰的四點做內插,由紅字 部分來看,只用到一個像素對映,這樣的方法只能稱為nearest neighborhood, 另外,將圖由320x240放大到640x480,是整數放大,用nearest neighborhood放大 後,雖然會有馬賽克的現象,不過效果應該也是相當不錯的。 小弟並沒有看完你所附的程式,只是從紅字那一行,很容易知道是不是內插法, 你的方法很可能是nearest neighborhood。我猜啦
happosai
高階會員


發表:93
回覆:228
積分:109
註冊:2002-09-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-01-06 10:03:36 IP:211.75.xxx.xxx 未訂閱
Dr. Dobb's Journal 2002, May 有一篇文章非常不錯,也是在講影像縮放 http://www.ddj.com/articles/2002/0205/ Image Scaling With Bresenham 這個演算法是由 Bresenham Line-Drawing Algorithm 延伸而來, 沒有使用乘法跟除法,速度非常快,但是仍能有不錯的品質...:)
bruce0211
版主


發表:157
回覆:668
積分:279
註冊:2002-06-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-01-06 16:57:55 IP:211.21.xxx.xxx 未訂閱
經過測試,以及比較下面兩篇文章的內容 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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-01-06 17:08:32 IP:211.21.xxx.xxx 未訂閱
引言: 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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-01-06 18:15:48 IP:211.75.xxx.xxx 未訂閱
前輩~下載 source code 是不用$的,你註冊成 Basic Level 就可以了, 很抱歉我手上沒有 source code,最後一次使用這個演算法是 1 年多前 的事情了,那時候是用來縮放指紋影像,效果很好... 附上errate http://www.compuphase.com/graphic/scale1errata.htm 作者還發表了不少 win32, animation, graphics 等相關文章, 真是個超級高手!!
系統時間:2024-05-04 2:13:26
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!