画像サイズの拡大・縮小の例です。拡大・縮小のアルゴリズムとして、[最近傍法], [線形補間法], [2次補間], [3次補間], [平均画素法] を用いての例を取り上げています。
また、アフィン変換による拡大・縮小・回転・移動に対し、補間を行う例も取り上げています。
アルゴリズムの詳細、とくに「平均画素法」に関しては取り上げているサイト等あまり見かけないですが、簡単に言うと、画像を一度拡大しておいてから、平均値を以って画像を縮小していくというものです。画像の拡大の倍数は、元の大きさと縮小する大きさの最小公倍数を用いて計算し、浮動小数点を用いない、整数の計算が行われるため計算は比較的高速・・というような説明をたまに見かけますが、最小公倍数が非常に大きくなってしまう場合等もありますので、そこ等へんはケースバイケースです。
元画像 | 平均画素法による縮小例 | アフィン変換例[3次補間] | ||
平均画素法の処理結果の綺麗さは下のような線画で比べると分かりやすいですね。2次補間等の縮小では、これ以上画像のサイズを縮めていくと文字が全く判別できない状態になってしまいますが、平均画素法ではこれより小さいサイズでも比較的判別できる状態を保てます。平均画素法自体が一種のローパスフィルターのような役割を有しているため、その他の画像では、全体的に平滑化されたような印象を受けるような感じになります。
元画像 | 2次補間による縮小例 | 平均画素法による縮小例 | ||
//----------------------------------------------------------------- // ipsize.cpp: // 画像サイズの変更 // Last Update: <2004/12/13 18:13:06 A.Murakami> //----------------------------------------------------------------- #include <windows.h> #include "wingui.h" #include "ipcommon.h" //----------------------------------------------------------------- #define SMALL_X 0.7321 // 縮小サイズx #define SMALL_Y 0.8732 // 縮小サイズy #define LARGE_X 1.28 // 拡大サイズx #define LARGE_Y 1.42 // 拡大サイズx #define DEG 35 // 回転角[degree] #define DX 5 // 移動量x #define DY -5 // 移動量y #define INTP_TYPE INTP_LN // アフィン変換/補間形式[INTP_NN,INTP_LN,INTP_BCC] #define SCALE_LARGE // 縮小・拡大の選択 //----------------------------------------------------------------- void toOrg(); void set_ipsize(); void iSmall1(); void iSmall2(); void iSmall3(); void iSmall4(); void iCSmall(); void iAffine(); //----------------------------------------------------------------- // メニューへの追加内容 //----------------------------------------------------------------- MenuInfo MI[] = { {"元画像",toOrg}, {"最近傍法",iSmall1}, {"線形補間法",iSmall2}, {"バイキュービック法",iSmall3}, {"面積平均法",iSmall4}, {"面積平均法(カラー)",iCSmall}, {"アフィン変換",iAffine}, {NULL,NULL} }; //----------------------------------------------------------------- // 元画像の表示 //----------------------------------------------------------------- void toOrg() { set_ip_window(); CopyMemory(lpBMP,lpOrgBMP,biSize); } //----------------------------------------------------------------- // 作業域の設定 //----------------------------------------------------------------- void set_ipsize() { int xsize,ysize; xsize = rint(iWidth*SMALL_X); ysize = rint(iHeight*SMALL_Y); set_ip_window(xsize,ysize); } //----------------------------------------------------------------- // 最近傍法[拡大・縮小] //----------------------------------------------------------------- void iSmall1() { set_ip_window(); LPBYTE iGray=GetGray(); #ifdef SCALE_LARGE nn_scale(iGray,LARGE_X,LARGE_Y); #else nn_scale(iGray,SMALL_X,SMALL_Y); set_ipsize(); #endif // 表示用 GrayToColor(iGray,lpBMP); // 後片付け GlobalFree(iGray); } //----------------------------------------------------------------- // 線形補間法[拡大・縮小] //----------------------------------------------------------------- void iSmall2() { set_ip_window(); LPBYTE iGray=GetGray(); #ifdef SCALE_LARGE linear_scale(iGray,LARGE_X,LARGE_Y); #else linear_scale(iGray,SMALL_X,SMALL_Y); set_ipsize(); #endif // 表示用 GrayToColor(iGray,lpBMP); // 後片付け GlobalFree(iGray); } //----------------------------------------------------------------- // バイキュービック法[拡大・縮小] //----------------------------------------------------------------- void iSmall3() { set_ip_window(); LPBYTE iGray=GetGray(); #ifdef SCALE_LARGE bcc_scale(iGray,LARGE_X,LARGE_Y); #else bcc_scale(iGray,SMALL_X,SMALL_Y); set_ipsize(); #endif // 表示用 GrayToColor(iGray,lpBMP); // 後片付け GlobalFree(iGray); } //----------------------------------------------------------------- // 平均画素法による縮小 //----------------------------------------------------------------- void iSmall4() { set_ip_window(); LPBYTE iGray=GetGray(); #ifdef SCALE_LARGE sqm_scale(iGray,LARGE_X,LARGE_Y); #else sqm_scale(iGray,SMALL_X,SMALL_Y); set_ipsize(); #endif // 表示用 GrayToColor(iGray,lpBMP); // 後片付け GlobalFree(iGray); } //----------------------------------------------------------------- // 平均画素法による縮小[カラー] //----------------------------------------------------------------- void iCSmall() { toOrg(); #ifdef SCALE_LARGE c_sqm_scale(lpBMP,LARGE_X,LARGE_Y); #else c_sqm_scale(lpBMP,SMALL_X,SMALL_Y); set_ipsize(); #endif } //----------------------------------------------------------------- // アフィン変換 //----------------------------------------------------------------- void iAffine() { toOrg(); #ifdef SCALE_LARGE c_affine_transform(lpBMP,INTP_TYPE,LARGE_X,LARGE_Y,DEG,DX,DY); #else c_affine_transform(lpBMP,INTP_TYPE,SMALL_X,SMALL_Y,DEG,DX,DY); #endif } |