今回opencvを用いて画像を読み込み、画像処理の実装部分は自力で書いているという状況です。
http://imagingsolution.blog107.fc2.com/ ... y-193.html
こちらのサイトに書いてあるアルゴリズムを参考にプログラムを一通り書き終え、
デバッグを行ったところ
****初回の例外が発生しました: 0xC0000005: 場所 ******* を書き込み中にアクセス違反が発生しました。
というエラーが、画素の端の例外処理を行っている部分で置きました。
具体的にはあとで記述する
ur = labelmatrix[y - 1][x + 1];
のところが不正アクセスを行っている(?)らしいのですが自分としては考えうる例外の分岐を書いたつもりでまったく解決法が思いつきません。
もしよろしければ教えてもらえないでしょうか。
void labeling(void)
{
IplImage *binaryImage;
start = clock(); //処理時間計測開始
binaryImage = cvLoadImage("../result/binary.jpg", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
if (binaryImage == NULL)
{
printf("画像が見つかりませんでした\n");
exit(-1);
}
uchar * bImg = (uchar*)binaryImage->imageData;
int bStep = binaryImage->widthStep;
int i;
int ur, up, ul, lt; //右上、上、左上、左の変数
int min = 0; //ラベルの最小値
int labeltable[HEIGHT*WIDTH / 4]; //ルックアップテーブル
int labelcount = 0; //ラベル番号
int comp[4] = {}; //最小判定の入れ物
int **labelmatrix; //ラベル配列の確保
labelmatrix = (int **)malloc(sizeof(int*)*HEIGHT);
if (labelmatrix == NULL){
printf("配列が確保できませんでした\n");
exit(1);
}
for (y = 0; y < HEIGHT; y++)
{
labelmatrix[y] = (int*)malloc(sizeof(int)*WIDTH);
}
for (y = 0; y < HEIGHT; y++){ //配列の中身の初期化
for (x = 0; x < WIDTH; x++){
labelmatrix[y][x] = 0;
}
}
int area[HEIGHT*WIDTH / 4] = {};
int check = 0;
for (i = 1; i < (HEIGHT*WIDTH / 4); i++){ //ルックアップテーブルの作製
labeltable[i] = i;
}
for (y = 0; y < HEIGHT; y++)
{
for (x = 0; x < WIDTH; x++)
{
if ((uchar)bImg[bStep*y + x] > 200)//もし白なら
{
//例外処理 端っこ
if (x == 0 && y > 1) //左端(原点除く)
{
ul = 0; lt = 0;
}
else if (y == 0 && x > 1) //上端(原点除く)
{
ur = 0; up = 0; ul = 0;
}
else if (y == 0 && x == 0) //原点
{
ur = 0; up = 0; ul = 0; lt = 0;
}
else if (y > 1 && x == WIDTH - 1) //右端(右上除く)
{
ur = 0;
}
else
{
ur = labelmatrix[y - 1][x + 1];
up = labelmatrix[y - 1][x];
ul = labelmatrix[y - 1][x - 1];
lt = labelmatrix[y][x - 1];
}
if (ur == 0 && up == 0 && ul == 0 && lt == 0) //右上、上、左上、左のラベル番号が0なら
{
labelcount++; //ラベルをインクリメント
labelmatrix[y][x] = labelcount; //ラベル表に書き込む
area[labelcount]++; //ラベル番号の面積を加算
}
else if (ur != 0 || up != 0 || ul != 0 || lt != 0) //一つでも0以外があれば
{
if (ur != 0) //0以外であれば最小を代入、その後0以外があれば比較して更新していく
{ //同時に面積も加算しているが、のちにラベル番号を更新した際に加減する
min = labelmatrix[y - 1][x + 1]; //一番最初なのでとりあえず最小値とする
check++; //最小が代入されたかチェック
comp[0] = labelmatrix[y - 1][x + 1]; //比較用配列に代入
area[labelmatrix[y - 1][x + 1]]++; //面積加算
}
if (up != 0)
{
if (check != 0) //最小が代入されていたら比較
{
if (labelmatrix[y - 1][x] < min)
min = labelmatrix[y - 1][x];
}
else //代入されていなかったら代入
{
min = labelmatrix[y - 1][x];
check++;
}
comp[1] = labelmatrix[y - 1][x]; //比較用配列に代入
area[labelmatrix[y - 1][x]]++; //同じラベルの面積を加算
}
if (ul != 0)
{
if (check != 0){
if (labelmatrix[y - 1][x - 1] < min)
min = labelmatrix[y - 1][x - 1];
}
else
{
min = labelmatrix[y - 1][x - 1];
check++;
}
comp[2] = labelmatrix[y - 1][x - 1]; //比較用配列に代入
area[labelmatrix[y - 1][x - 1]]++; //面積加算
}
if (lt != 0)
{
if (check != 0)
{
if (labelmatrix[y][x - 1] < min)
min = labelmatrix[y][x - 1];
}
else
{
min = labelmatrix[y][x - 1];
}
comp[3] = labelmatrix[y][x - 1]; //比較用配列に代入
area[labelmatrix[y][x - 1]]++; //面積加算
}
check = 0; //チェックを初期化
for (y = 0; y < 4; y++)
{
if (comp[y] != 0) //中身が0でなければ
labeltable[comp[y]] = min; //ルックアップテーブルの更新
comp[y] = 0; //比較用配列の初期化
}
labelmatrix[y][x] = min; //ラベルを代入
}
}
}
}
for (y = 0; y < HEIGHT; y++)
{
for (x = 0; x < WIDTH; x++)
{
if (labelmatrix[y][x] != labeltable[labelmatrix[y][x]])
{
area[labelmatrix[y][x]]--; //面積引いて
do{
labelmatrix[y][x] = labeltable[labelmatrix[y][x]];
} while (labelmatrix[y][x] != labeltable[labelmatrix[y][x]]); //ルックアップテーブルの番号とラベル番号が一致するまでループ
area[labelmatrix[y][x]]++; //面積足して
}
}
}
for (x = 0; x < labelcount; x++)
{
if (area[x] != 0)
printf("ラベル番号%dの面積は\t%d\n", x, area[x]);
}
for (y = 0; y < HEIGHT; y++) //ラベル配列の開放
free(labelmatrix[y]);
free(labelmatrix);
end = clock();
printf("処理時間は%d\n", end - start);
}