AR.Droneで物体検出
今回は色ベースで物体検出をしていきます。
色の抽出にはHSV表色系を用います。
手順は以下の通りです。
1. RGBからHSVに変換
2. 閾値処理で2値化
3. 一番大きな輪郭を抽出
2値化に関してはcvInRangeS()を使っています。
cvThreshold()の方がメジャーですが、Hue==0を扱うことができません。
cvBoundingRect()で矩形(くけい)を包含する四角形を描画しています。
cvMoment()を使えば重心位置を算出できます。

見える、私にも見えるぞ!
色の抽出にはHSV表色系を用います。
手順は以下の通りです。
1. RGBからHSVに変換
2. 閾値処理で2値化
3. 一番大きな輪郭を抽出
2値化に関してはcvInRangeS()を使っています。
cvThreshold()の方がメジャーですが、Hue==0を扱うことができません。
#include "ardrone/ardrone.h"
#define KEY_DOWN(key) (GetAsyncKeyState(key) & 0x8000)
#define KEY_PUSH(key) (GetAsyncKeyState(key) & 0x0001)
// --------------------------------------------------------------------------
// main(引数の数、引数リスト)
// メイン関数です
// 戻り値 正常終了:0 エラー:-1
// --------------------------------------------------------------------------
int main(int argc, char **argv)
{
// AR.Droneクラス
ARDrone ardrone;
// 初期化
if (!ardrone.open()) {
printf("初期化に失敗しました\n");
return -1;
}
// 閾値
int minH = 0, maxH = 255;
int minS = 0, maxS = 255;
int minV = 0, maxV = 255;
// ウィンドウ
cvNamedWindow("binalized");
cvCreateTrackbar("H max", "binalized", &maxH, 255);
cvCreateTrackbar("H min", "binalized", &minH, 255);
cvCreateTrackbar("S max", "binalized", &maxS, 255);
cvCreateTrackbar("S min", "binalized", &minS, 255);
cvCreateTrackbar("V max", "binalized", &maxV, 255);
cvCreateTrackbar("V min", "binalized", &minV, 255);
cvResizeWindow("binalized", 0, 0);
// メインループ
while (!GetAsyncKeyState(VK_ESCAPE)) {
// 更新
if (!ardrone.update()) break;
// 画像を取得
IplImage *image = ardrone.getImage();
// HSVに変換
IplImage *hsv = cvCloneImage(image);
cvCvtColor(image, hsv, CV_RGB2HSV_FULL);
// 2値化画像
IplImage *binalized = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
// 2値化
CvScalar lower = cvScalar(minH, minS, minV);
CvScalar upper = cvScalar(maxH, maxS, maxV);
cvInRangeS(hsv, lower, upper, binalized);
// 結果を表示
cvShowImage("binalized", binalized);
// ノイズ除去
cvMorphologyEx(binalized, binalized, NULL, NULL, CV_MOP_CLOSE);
// 輪郭検出
CvSeq *contour = NULL, *maxContour = NULL;
CvMemStorage *contourStorage = cvCreateMemStorage();
cvFindContours(binalized, contourStorage, &contour, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// 一番大きな輪郭を抽出
double max_area = 0.0;
while (contour) {
double area = fabs(cvContourArea(contour));
if (area > max_area) {
maxContour = contour;
max_area = area;
}
contour = contour->h_next;
}
// 検出できた
if (maxContour) {
// 結果を表示
CvRect rect = cvBoundingRect(maxContour);
CvPoint minPoint, maxPoint;
minPoint.x = rect.x;
minPoint.y = rect.y;
maxPoint.x = rect.x + rect.width;
maxPoint.y = rect.y + rect.height;
cvRectangle(image, minPoint, maxPoint, CV_RGB(0,255,0));
}
// メモリ解放
cvReleaseMemStorage(&contourStorage);
// 表示
cvShowImage("camera", image);
cvWaitKey(1);
// メモリ解放
cvReleaseImage(&hsv);
cvReleaseImage(&binalized);
}
// さようなら
ardrone.close();
return 0;
}
cvBoundingRect()で矩形(くけい)を包含する四角形を描画しています。
cvMoment()を使えば重心位置を算出できます。

見える、私にも見えるぞ!