「写真の円式補正Pixiaでの実装」の編集履歴(バックアップ)一覧はこちら

写真の円式補正Pixiaでの実装 - (2010/04/09 (金) 20:04:47) の最新版との変更点

追加された行は緑色になります。

削除された行は赤色になります。

このページでは[[写真の円式補正アルゴリズム]]をPixiaで実装をする。 このサイトと「C言語で学ぶ初めてのアルゴリズム」を参考にコードを作成する。 http://homepage2.nifty.com/~maru_tacmi/filter/3.htm 主にこのコードを拡張して、アルゴリズムを実装する。 http://homepage2.nifty.com/~maru_tacmi/filter/3/ftest1.C 画像配列=F(写真) Fは単写 -処理済配列=画像配列と同じサイズの画像データを格納するための配列 繰り返し処理 -処理済配列=K(画像配列,処理済配列) 繰り返し -完成画像=F1(処理済配列) 上記コードを参考にプログラムを作成する。 手順0 元画像を加工するために画像データを全部配列に取り出す処理 手順1 まずは画像配列から指定した範囲を切り取りサブセット配列に確保する処理を作る。 手順2 次に切り取った部分を変更する関数Kを作る 手順3 Kの出力結果を元に新しい処理済配列の指定した範囲に半透明円を貼り付ける処理 手順4 できた配列を元に新しい画像を作り出す処理。 -2010/3/14プログラム開始。 まだ処理未実装、とりあえずページを作った段階。 -手順0実装予定 ---- 名前 堀江伸一 住所 兵庫県加古川市加古川町南備後79-16 //サンプルコードを実装中 //管理人のプログラム適正は0に近いので恐ろしく低レベルで時間がかかっています //多分プログラムミスが入りまくる可能性アリ #include <windows.h> #include <windowsx.h> #include <string.h> #include <stdio.h> #include "pixiadll.h" #include "px_samp.h" HINSTANCE hInst; int CALLBACK _DllMainCRTStartup( HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved ) { hInst = hInstance; return(1); } /* テスト用の設定パラメータ 何らかの設定ダイアログをもつフィルタの場合にはこのように使用します。 */ typedef struct tagSAMPLE{ int a; int b; }SAMPLE; SAMPLE sample; /* 設定パラメータをもつフィルタでは、このように設定パラメータを読み書きする。 */ BOOL ReadData( LPSTR szDir ) { unsigned char szDataDir[256]; HFILE hFile; strcpy( szDataDir, szDir ); strcat( szDataDir, "px_samp.dat" ); if(-1==(hFile=_lopen( szDataDir,OF_READ|OF_SHARE_DENY_WRITE))){ sample.a = 0; sample.b = 0; return( TRUE ); } _lread( hFile,(LPBYTE)&sample, sizeof(SAMPLE)); _lclose( hFile ); return( TRUE ); } BOOL WriteData( LPSTR szDir ) { unsigned char szDataDir[256]; HFILE hFile; strcpy( szDataDir, szDir ); strcat( szDataDir, "px_samp.dat" ); if(-1==(hFile=_lcreat(szDataDir,0))) return( FALSE ); _lwrite( hFile,(LPBYTE)&sample, sizeof(SAMPLE)); _lclose( hFile ); return( TRUE ); } /*------------------------------------------------------------ フィルタのタイトルを得る 入力: hWnd.. オーナーウインドウハンドル 通常は使用しないが,NULLの場合も考慮すること 出力: fOpt.. 詳細設定をもつかどうかのフラグ ver.. DLL仕様のバージョン(Pixiaでは10にする。) info.. リストボックスに表示する文字列 */ BOOL FilterGetTitle( HWND hWnd, LPSTR info, BOOL *opt, int *ver ) { strcpy( info, "テストフィルタ" ); *opt = TRUE; *ver = 10; return( TRUE ); } /*------------------------------------------------------------ フィルタの実行 入力: */ BOOL FilterProc(HWND hWnd, LAYERINFO *li, SETLINEFUNC *sf, GETLINEFUNC *gf, LPSTR szDir,LPBYTE lpExt) { int i, j; int buff_size; LPBYTE lpWork; ReadData( szDir ); // 設定したパラメータを読み込む buff_size = (li->cx * 3 + 100); lpWork = (LPBYTE)GlobalAllocPtr( GHND, buff_size ); int ps[li->cy][li>-cx][2]; //データを配列に移す作業 j行i列、RGBの赤、緑、青 if( lpWork == NULL ) return( FALSE ); for( j = 0; j < li->cy; j ++ ){ // 進行状況の表示 if( j % 5 ==0 ){ SendMessage( hWnd, MM_DISPINFO, INFO_PERCENTAGE, j * 100 / li->cy ); } // 画素情報を得る gf->GetLine( j, 0, li->cx-1, lpWork, -1 ); for( i = 0; i < li->cx;i ++ ){ // 赤ゲット ps[j][i][0] = lpWork[i*3]; // 青ゲット ps[j][i][1] = lpWork[i*3+1]; // 緑ゲット ps[j][i][2] = lpWork[i*3+2]; } } GlobalFreePtr( lpWork ); // 画素情報を保存する。 //sf->SetLine( j, 0, li->cx-1, lpWork, -1 ); // 進行状況表示の終了 SendMessage( hWnd, MM_DISPINFO, INFO_NONE, 0 ); return( TRUE ); } BOOL pictToCircle(LAYERINFO *li, int *ps,int size,int x,int y) { int startX; int startY; int endX; int endY; startX=CutNum(0,li->cx,x-size); startY=CutNum(0,li->cy,y-size); endX =CutNum(0,li->cx,x+size); endY =CutNum(0,li->cy,y+size); int sizeX=endX-startX; int sizeY=endY-startY; float ar=0; float ag=0; float ab=0; for(j=0;j<sizeY;j++){ for(i=0;i<sizeX;i++){ //ここで画像処理を行う、まずは色空間の色の平均を取り、平均から一定距離以内にたくさんの色があればその色を基準色とする、この処理には色々な関数があるよね //実はこのコードを書いた人間のプログラマ適正は0に近く、そして私にはプログラム書いてくれるような友達がいないのだった(爆)だからコードにミスがあっても許してね //人間が3原色で色を認識しているのはよかったのか悪かったのか、4原色だったら、4次元空間で勉強が大変になったかも? ar+=ps[j+startY][i+startX][0]; ag+=ps[j+startY][i+startX][1]; ab+=ps[j+startY][i+startX][2]; } } float areaSize=((sizeX+1)*(sizeY+1)); ar/=areaSize; ag/=areaSize; ab/=areaSize; float count=0; float temp=0; for(j=0;j<sizeY;j++){ for(i=0;i<sizeX;i++){ temp+=((ps[j+startY][i+startX][0]-ar)^2; temp+=((ps[j+startY][i+startX][1]-ag)^2; temp+=((ps[j+startY][i+startX][2]-ab)^2; temp=temp^0.5 //色空間内での平均からの距離が50以下ならcountする if(temp<50){ count++; } //処理ここまで } } //色空間内での散らばりが十分に小さいなら色を認める。 //比率を求める計算式を設定しても良いかもしれない? if (count/areaSize>0.8){ }else{ } } int function CutNum(int min,int max,int l){ if(min>l){ l=min; } if(max<l){ l=max; } return (l); } static BOOL CALLBACK OptDlgProc( HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam ) { switch( uMessage ){ case WM_COMMAND: switch( LOWORD(wParam)){ case IDOK: EndDialog( hDlg, TRUE ); break; case IDCANCEL: EndDialog( hDlg, FALSE ); break; } break; case WM_SYSCOMMAND: if( LOWORD( wParam ) == SC_CLOSE ){ EndDialog( hDlg, FALSE ); } break; } return( FALSE ); } /* 詳細設定 */ BOOL FilterOption( HWND hWnd, LPSTR szDir, BYTE *lpExt ) { ReadData( szDir ); // ダイアログでのパラメータ設定の例 if( DialogBox( hInst, "sampledlg", hWnd, OptDlgProc )){ WriteData( szDir ); } return( TRUE ); }
このページでは[[写真の円式補正アルゴリズム]]をPixiaで実装をする。 このサイトと「C言語で学ぶ初めてのアルゴリズム」を参考にコードを作成する。 http://homepage2.nifty.com/~maru_tacmi/filter/3.htm 主にこのコードを拡張して、アルゴリズムを実装する。 (http://homepage2.nifty.com/~maru_tacmi/filter/3/ftest1.C)旧版 ちょっと考え直して2010/4/20現在 http://www.pixia.jp/download/pixiafilter.zip を拡張して作ることにしました。 px_samp.Cのみを拡張して作っています。 &ref(px_samp2.txt) ←ソースコード 近況(ただ今コンパイルとバグつぶしと、画像処理にかんする適切なパラメータを探しています) 画像配列=F(写真) Fは単写 -処理済配列=画像配列と同じサイズの画像データを格納するための配列 繰り返し処理 -処理済配列=K(画像配列,処理済配列) 繰り返し -完成画像=F1(処理済配列) 上記コードを参考にプログラムを作成する。 手順0 元画像を加工するために画像データを全部配列に取り出す処理 手順1 まずは画像配列から指定した範囲を切り取りサブセット配列に確保する処理を作る。 手順2 次に切り取った部分を変更する関数Kを作る 手順3 Kの出力結果を元に新しい処理済配列の指定した範囲に半透明円を貼り付ける処理 手順4 できた配列を元に新しい画像を作り出す処理。 -2010/3/14プログラム開始。 まだ処理未実装、とりあえずページを作った段階。 -手順0実装予定 [[写真の円式補正法C#での実装1]] ---- コード製作者 名前 堀江伸一 住所 兵庫県加古川市加古川町南備後79-16 現在の主要なコード、実は作りかけ。 &ref(px_samp.txt) &ref(px_samp2.txt) 最新版大体の内容は実装済み、いまだ未コンパイルなのでコンパイラに通してコンパイルエラーをつぶしてからテストをする予定 Cは苦手な上、管理人はプログラムが超苦手なので多分コードミスがあります。 円を描くかどうかを判定するための四角い範囲を少しずつずらして、変化した部分だけを求めてから平均や壁画の判断を計算したほうがよいのでしょうが、とりあえず動くコードを提供することを目的にしています。 もっと賢い方法では行列とか漸化式を立てて一瞬で求めるのでしょうが、管理人そこまでする気は無いです。 高速化を目指すなら、まずは計算において差分の部分を四則演算の線形で扱えるにしておき差分の変化だけを計算し、その計算回数を最小化すればいいんだよな? [[写真の円式補正法Pixiaでの実装予備ページ]] ご意見のあるかたはこちらへ。 #comment

表示オプション

横に並べて表示:
変化行の前後のみ表示: