輪郭線追跡プログラム
/* 輪郭線追跡プログラム 8連結 * 前提:画像の最外周は画素が存在しないこと(存在すると実行時エラー) * ドーナツ型の図形もおそらく対応 * 画像は擬似配列を用いている(1が画素とする) */ #include<iostream> #define SIZE 20 #define WHITE 0 #define BLACK 1 #define CHECK -1 using namespace std; void output(void); //擬似画像表示関数 int OutlineTrace();//輪郭線追跡 int TraceAround(int,int,int);//画像の周囲をラベル付けする struct Point{ //座標を格納する構造体 int x; int y; }; int gaso[SIZE][SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, 0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,0, 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0, 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; int main() { output(); OutlineTrace(); output(); } void output() //擬似画像の出力 { for(int i = 0 ; i < SIZE ; i++){ for(int j = 0 ; j < SIZE ; j++){ if(gaso[i][j] == WHITE) cout << "○"; else if(gaso[i][j] == BLACK) cout << "●"; else cout << "▲"; } cout << endl; } cout << endl; } int OutlineTrace(){ for(int i = 0 ; i < SIZE ; i++){ for(int j = 0 ; j < SIZE ; j++){ if(gaso[i][j] == BLACK){ //BLACKがあれば周りを走査 // cout << "画素" << i << "," << j << "からトレース開始" << endl; TraceAround(i,j,0); // output(); } if(gaso[i][j] == CHECK){ //CHECK済みであれば次のWHITEまで読み飛ばし while(gaso[i][j] != WHITE){ j++; } } } } return 0; } //画像の周りをトレース /* Pを取り囲む要素 Pの周囲の座標 p3 p2 p1 P+offset[3] P+offset[2] P+offset[1] p4 P p0 P+offset[4] P P+offset[0] p5 p6 p7 P+offset[5] P+offset[6] P+offset[7] 画素を発見した位置(direction)と探索を開始する位置(sd)には sd = (direction + 5) % 8 の関係がある */ int TraceAround(int y,int x,int direction){ const Point offset[8] = { {1,0},{1,-1}, //8近傍の相対位置(オフセット) {0,-1},{-1,-1}, {-1,0},{-1,1}, {0,1},{1,1} }; int startx = x,starty = y; //開始地点を保存 // gaso[y][x] = CHECK; do{ int sd = (direction + 5) % 8; //探索を開始する方向(SearchDirection) for(int i = 0;i < 8; ++i){ //ここでもし周りに何も見つからなかったら無限ループになるので後で修正 int arroundx = x + offset[(sd + i) % 8].x; int arroundy = y + offset[(sd + i) % 8].y; if(gaso[arroundy][arroundx] != WHITE){ y = arroundy; x = arroundx; gaso[y][x] = CHECK; // cout << "画素" << y << "," << x << "をチェック" << endl; direction = (sd + i) % 8; break; } } }while(startx != x || starty != y); //開始地点に戻ってくるまでループ return 0; }