2016/08/21
前回の続きです。前回詳しくお話しできなかった内容についてお話します。まずは、特徴量(面積)での検出オブジェクトの抽出と四角形の囲みについてです。
//特徴量で選択
void ImageProc::LabelSelect(int labelno, Mat statin, Mat centin) {
int k = 0;
array<int, 2>^ LabellingResTemp = gcnew array<int, 2>(10000, 6);
array<double, 2>^ LabellingCentTemp = gcnew array<double, 2>(10000, 2);
for (int i = 1; i <= labelno; i++) {
for (int j = 0; j <= 5; j++) {
LabellingResTemp[i, j] = statin.at<int>(i, j);
}
LabellingCentTemp[i, 0] = centin.at<double>(i, 0); //x
LabellingCentTemp[i, 1] = centin.at<double>(i, 1); //y
//areaで選別
if (LabellingResTemp[i, 4] > areaborder) {
k++;
for (int j = 0; j <= 5; j++) {
LabellingRes[k, j] = LabellingResTemp[i, j];
}
LabellingCent[k, 0] = LabellingCentTemp[i, 0];
LabellingCent[k, 1] = LabellingCentTemp[i, 1];
}
}
DetectObjNo = k;
//囲みと番号を付ける
for (int i = 1; i <= DetectObjNo; i++) {
char strtemp[10];
snprintf(strtemp, sizeof(strtemp), "%d", i);
cv::String labelstr = strtemp;
LabelBox(labelstr, LabellingRes[i, 0], LabellingRes[i, 1], LabellingRes[i, 2], LabellingRes[i, 3]);
}
}
このコードでは、ラベリングで検出された全オブジェクトについて、面積で「再ふるい直し」をしています。ラベリングで求められた結果を引数として与え、16~23行目で面積しきい値areaborderより大きなオブジェクトを選んで、再カウントしています。29~35行目は、面積でふるわれたオブジェクトを四角で囲み、番号をつける部分です。LabelBox関数は自作関数で、以下のコードです。
//検出オブジェクトの囲み
void ImageProc::LabelBox(cv::String slabelno, int ileft, int itop, int iwidth, int iheight) {
rectangle(workimage[processcounter], Point(ileft, itop), Point(ileft + iwidth, itop + iheight), Scalar(0, 255, 255), 1, 8, 0);
int center_x = (int)((double)ileft + (double)(iwidth / 2)); //中心x
int center_y = (int)((double)itop + (double)(iheight / 2)); //中心y
line(workimage[processcounter], Point(center_x, center_y - 2), Point(center_x, center_y + 2), Scalar(0, 255, 255), 1, 8, 0);
line(workimage[processcounter], Point(center_x - 2, center_y), Point(center_x + 2, center_y), Scalar(0, 255, 255), 1, 8, 0);
int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
double fontScale = 0.5;
putText(workimage[processcounter], slabelno, Point(center_x + 5, center_y + 5), fontFace, fontScale, Scalar(0, 255, 255), 1, 8);
}
ラベル番号と左上のx, y座標(Left, Top座標)とWidth、Heightのデータを引数として、4行目で四角形を描画しています。6, 7行目で四角形の中心座標(フェレ径の中心)を求め、9, 10行目でその位置に十字マークを入れています。最後に、14行目でラベル番号を文字記入しています。
ここで、標準ラベリング関数を実行した際に出てくる重心座標、つまり、自作関数LabelSelectで出てくる重心座標(Gx, Gy) = (LabellingCentTemp[i, 0], LabellingCentTemp[i, 1])と、自作関数LabelBoxの中心座標(Cx, Cy)の違いを確認しておきます。

中心座標と異なり、重心座標は正しくオブジェクトの重心位置を示していることが確認できました。当たり前といえばそうかもしれませんが、念のための確認でした。