2011/12/12

OpenCVで作るビジョンプログラム(3)

こんにちは、Shinpukuです。

今回は色抽出についてお話しします。

カメラから得た画像の中には、ボールや白線といった私たちが欲しい情報が含まれています。
具体的には黄色(オレンジ)、緑、白、黒がそれに当たります。

色抽出の前にカメラ画像の色空間をRGBからYUV(YCbCr)に変換します。
// RGB->YUV色変換
cvCvtColor(images.cvCamera, images.cvCameraYUV, CV_RGB2YCrCb);
cvSplit(images.cvCameraYUV, images.cvY, images.cvU, images.cvV, NULL);

YUVは明るさの変化に強く、ロボカップで用いられている色を簡単に表現することができます。
カメラからYUV422で出力されるのですがRGB->HSV変換の名残や僕の勉強不足のせいでこうなっています。

YUVの各チャンネルで閾値を設定して画像を2値化します。

OpenCVで代表的なものはcvThreshold、cvInRangeS、cvLUTですが、私たちのプログラムでは速度を優先してcvThresholdを用いています。
// 色抽出
cvThreshold(images.cvY, images.cvYellow, thresholds.maxYellowY, 0, CV_THRESH_TOZERO_INV);
cvThreshold(images.cvYellow, images.cvYellow, thresholds.minYellowY, 255, CV_THRESH_BINARY);
cvThreshold(images.cvU, images.cvBuf, thresholds.maxYellowU, 0, CV_THRESH_TOZERO_INV);
cvThreshold(images.cvBuf, images.cvBuf, thresholds.minYellowU, 255, CV_THRESH_BINARY);
cvAnd(images.cvYellow, images.cvBuf, images.cvYellow);
cvThreshold(images.cvV, images.cvBuf, thresholds.maxYellowV, 0, CV_THRESH_TOZERO_INV);
cvThreshold(images.cvBuf, images.cvBuf, thresholds.minYellowV, 255, CV_THRESH_BINARY);
cvAnd(images.cvYellow, images.cvBuf, images.cvYellow);

cvLUTは3ch→1chへの変換が出来ず、なぜかcvThresholdよりも遅いため使っていません。

cvInRangeSを使うと低速ですが、綺麗なコードになります。
// 色抽出
CvScalar lower = cvScalar(thresholds.minYellowY, thresholds.minYellowU, thresholds.minYellowV);
CvScalar upper = cvScalar(thresholds.maxYellowY, thresholds.maxYellowU, thresholds.maxYellowV);
cvInRangeS(images.cvCameraYUV, lower, upper, images.cvYellow);

色抽出の結果は以下のようになります。

0 件のコメント: