第4章 画像補正 【リスト4-1】 色変化の抽出 #include "myWin.h" #include "math.h" #define XST 420 #define YST 10 #define GWIDTH 400 #define GHIGHT 400 #define RED(X) (X & 0xFF) #define GREEN(X) ((X>>8) & 0xFF) #define BLUE(X) ((X>>16) & 0xFF) static HBITMAP hBM[2];static HDC hBuff[2]; static BITMAP bM[2]; void clearBitmap(int i){//ビットマップのクリア SelectObject(hBuff[i], GetStockObject(NULL_PEN)); PatBlt(hBuff[i], 0,0,GWIDTH,GHIGHT,WHITENESS);//黒塗り } void createBitmap(HWND hw){//ビットマップの設定 HDC hdc=GetDC(hw); for(int i=0;i<2;i++){ hBM[i]=CreateCompatibleBitmap(hdc,GWIDTH,GHIGHT); hBuff[i]=CreateCompatibleDC(hdc); SelectObject(hBuff[i], hBM[i]); clearBitmap(i); } } int pixel(int i, int j){//画像1からピクセルを取り出す return GetPixel(hBuff[1], i,j); } void setPixel(int i, int j, COLORREF C){//画像0にピクセルを設定する SetPixel(hBuff[0], i,j, C); } void drawEdge(){ COLORREF C1,C2,C3,R1,R2, G1,G2,B1,B2,Z; for(int i=0;i255) R1=255;if(G1>255) G1=255;if(B1>255) B1=255; setPixel(i,j,RGB(R1,G1,B1)); } } } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ drawEdge(); InvalidateRect(hw,NULL,TRUE); } void procRButtonDown(HWND hw, WPARAM wp,LPARAM lp){ clearBitmap(0);//画像0をクリア InvalidateRect(hw,NULL,TRUE); } void procCreate(HWND hw, WPARAM wp,LPARAM lp){//初期処理 createBitmap(hw);MoveWindow(hw,0,0,850,460,TRUE); hBM[1]=LoadBitmap(hInstance, TEXT("suzume"));//画像1に表示 GetObject(hBM[1],sizeof(BITMAP), &bM[1]); InvalidateRect(hw,NULL,TRUE); } void procPaint(HWND hw, WPARAM wp,LPARAM lp){//画面表示 PAINTSTRUCT ps; HDC hdc = BeginPaint(hw,&ps); SelectObject(hBuff[0],hBM[0]);SelectObject(hBuff[1],hBM[1]); BitBlt(hdc,10,YST,GWIDTH, GHIGHT, hBuff[0], 0,0,SRCCOPY); BitBlt(hdc,XST,YST,GWIDTH, GHIGHT, hBuff[1], 0,0,SRCCOPY); EndPaint(hw,&ps); } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate(hw,wp,lp); return 0; case WM_LBUTTONDOWN : procLButtonDown(hw,wp,lp); return 0; case WM_RBUTTONDOWN : procRButtonDown(hw,wp,lp); return 0; case WM_PAINT : procPaint (hw,wp,lp); return 0; } return DefWindowProc(hw,msg,wp,lp); } (線画にする) C1=0; if(R1>40||G1>40||B1>40)C1=0xFFFFFF; setPixel(i,j,C1); 【リスト4-2】 モザイク処理 void drawMosaic(){ BitBlt(hBuff[0],0,0,GWIDTH, GHIGHT, hBuff[1], 0,0,SRCCOPY); int ist=80, ied=160, jst=80, jed=160;//モザイク範囲 for(int i=ist; i255) R1=255; G1=mixColor(G, G2, AG);if(G1>255) G1=255; B1=mixColor(B, B2, AB);if(B1>255) B1=255; setPixel(i,j,RGB(R1,G1,B1)); } } 【リスト4-4】 フィルタ行列の計算関数 void procFilter(int filter[3][3]){ for(int i=1;i0) {R/=T; G/=T; B/=T;} if(R>255)R=255;if(G>255)G=255;if(B>255)B=255; setPixel(i,j,RGB(R,G,B)); } } 【リスト4-5】 画像平滑化(ぼかし効果)【リスト4-4】の関数を呼び出す。 void drawShade(){ int filter[3][3]={{1,1,1},{1,1,1},{1,1,1}}; procFilter(filter); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ drawShade(); InvalidateRect(hw,NULL,TRUE); } 【リスト4-6】 加重平均フィルタ【リスト4-4】の関数を呼び出す。 void weightedAvarage(){ int filter[3][3]={{1,1,1},{1,2,1},{1,1,1}}; procFilter(filter); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ weightedAvarage(); InvalidateRect(hw,NULL,TRUE); } 【リスト4-7】 メディアンフィルタ #define swap(type, X,Y) do{type T; T=X;X=Y; Y=T;}while(0) void drawMedian(){//メディアンフィルタ for(int i=1;i<(GWIDTH-1);i++)for(int j=0;j<(GHIGHT-1);j++){ int R=0,G=0,B=0, T=0, filter[9], k=0; for(int k1=0;k1<=2; k1++)for(int k2=0;k2<=2; k2++,k++) filter[k]=pixel(i+k1-1, j+k2-1); for(int k1=0;k1<8;k1++)for(int k2=8;k2>k1; k2--) if(filter[k2-1]>filter[k2]) swap(int,filter[k2-1],filter[k2]); setPixel(i,j,filter[4]); } } 【リスト4-8】 鮮明化フィルタ【リスト4-4】の関数を呼び出す。 void distinctFilter(){ int filter[3][3]={{-1,-1,-1},{-1,9,-1},{-1,-1,-1}}; procFilter(filter); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ weightedAvarage(); InvalidateRect(hw,NULL,TRUE); } 【リスト4-9】 もうひとつの鮮明化フィルタ void procFilter2(int filter[3][3], double alfa){ for(int i=1;i255)R=255; G=(int)(T*G);if(G>255)G=255; B=(int)(T*B);if(B>255)B=255; C=RGB(R,G,B); setPixel(i,j,C); } } void distinctFilter(){ int filter[3][3]={{-1,-1,-1},{-1,9,-1},{-1,-1,-1}}; procFilter2(filter, 0.5); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ distinctFilter(); InvalidateRect(hw,NULL,TRUE); } 【リスト4-10】 エッジ抽出フィルタ【リスト4-4】の関数を呼び出す。 void edgeFilter(){ int filter[3][3]={{-1,-2,1},{-2,0,2},{-1,2,1}}; procFilter(filter); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ edgeFilter(); InvalidateRect(hw,NULL,TRUE); } 【リスト4-11】 エッジ抽出フィルタの結果を線画に変換 void enphasisEdge(double Alfa){ int C,R,G,B, Z=(int)( 255.0 * 3.0 * Alfa); for(int i=0;ifilter[mx]) mx=k1; if(filter[k1]255)R=255;if(G>255)G=255;if(B>255)B=255; setPixel(i,j,RGB(R,G,B)); } void edgeFilter(){ int filter[3][3]={{1,0,0},{0,-1, },{0,0,0}}; procFilter4(filter); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ edgeFilter(); InvalidateRect(hw,NULL,TRUE); }