Ball Detection RTCs (C++)
単眼カメラを使って、特定の色のカラーボールを検出し、その位置を計測するRTコンポーネントを作成する方法を解説します。
▶ 更新履歴
1. はじめに
単眼カメラを使って、既知のボールの位置を計測するRTCを作成します。
ボールの位置計測アルゴリズムを用いたRTコンポーネントの作成方法を説明します。
アルゴリズムの説明はDistance Measurementをご覧ください。
今回は、以下のRTCを作成します。
-
BallDetection
画像から既知のカラーボールを検出し、位置を計測します。
-
WebCamera
Webカメラから画像を取得し、画像を転送します。
WebCamera RTCsで作成したものを再利用します。
-
TimedPoint3DConsoleOut
受け取ったTimedPoint3D型のデータをコンソール上に表示します。
2. BallDetection RTC
BallDetection RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
BallDetection
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
CAMERA
-
実行周期
30
-
アクションコールバック
onInitialize
onActivated
onDeactivated
onExecute
-
データポート
・cameraポート
ポート名(InPort) camera
データ型 CameraImage
変数名 camera
表示位置 LEFT
・point3dポート
ポート名(OutPort) point3d
データ型 TimedPoint3D
変数名 point3d
表示位置 RIGHT
-
言語
C++
use old build environment. (Linuxの場合)
■Windows OSの場合
テンプレートを生成したらCMakeを行い、ソリューションファイルを生成して下さい。
ソリューションを開いたら、以下の2つのプロジェクトにOpenCVをビルドするための、
追加のインクルード ディレクトリと追加のライブラリ ディレクトリ、追加の依存ファイルを設定して下さい。
また、Color Extractionの説明を見てimage_processing.hとcolor_extaction.cppを作成してください。
そのファイルもプロジェクトに追加してください。
-
BallDetectionプロジェクト
-
BallDetectionCompプロジェクト
追加の依存ファイルは、以下の3つになります。
■ソリューションの構成がDebugの場合
・opencv_core246d.lib
・opencv_highgui246d.lib
・opencv_imgproc246d.lib
■ソリューションの構成がReleaseの場合
・opencv_core246.lib
・opencv_highgui246.lib
・opencv_imgproc246.lib
*246は使用しているOpenCVのバージョンに合わせて設定してください。
■Linux OSの場合
Makefile.BallDetectionを開いて、OpenCVのヘッダファイルとライブラリを指定します。
Makefileの修正方法は、OpenCVを使用したRTCの作成方法を御覧ください。
プロジェクトの設定が終わったら、BallDetection.cppに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
-
#include <opencv2/highgui/highgui.hpp>
-
#include "image_processing.h"
-
-
hsv_threshold threshold;
-
-
RTC::ReturnCode_t BallDetection::onActivated(RTC::UniqueId ec_id)
-
{
-
threshold.hue_lower = m_hue_lower;
-
threshold.hue_upper = m_hue_upper;
-
threshold.saturation = m_saturation;
-
threshold.value = m_value;
-
-
return RTC::RTC_OK;
-
}
-
-
RTC::ReturnCode_t BallDetection::onDeactivated(RTC::UniqueId ec_id)
-
{
-
cv::destroyAllWindows();
-
-
return RTC::RTC_OK;
-
}
-
-
RTC::ReturnCode_t BallDetection::onExecute(RTC::UniqueId ec_id)
-
{
-
if (m_cameraIn.isNew()){
-
-
m_cameraIn.read();
-
-
if(m_camera.bpp == 24)
-
{
-
cv::Mat receive(m_camera.height, m_camera.width, CV_8UC3, &m_camera.pixels[0]);
-
cv::Mat binary = extract_color(receive, threshold);
-
-
cv::vector<cv::Vec3f> circles;
-
cv::HoughCircles(binary, circles, CV_HOUGH_GRADIENT, 1, binary.rows/8, 200, 10, 0, 0);
-
-
if(circles.size() > 0)
-
{
-
cv::Point2f center(circles[0][0], circles[0][1]);
-
-
m_point3d.data.z = m_ball_radius / circles[0][2] * m_f_per_s;
-
m_point3d.data.y = (center.x - m_camera.width / 2) * m_point3d.data.z / m_f_per_s;
-
m_point3d.data.x = (center.y - m_camera.height / 2) * m_point3d.data.z / m_f_per_s;
-
-
std::cout << "Z: " << m_point3d.data.z
-
<< " X: " << m_point3d.data.x
-
<< " Y: " << m_point3d.data.y << std::endl;
-
-
cv::circle(receive, center, 3, cv::Scalar(0, 255, 0), -1, 8, 0);
-
cv::circle(receive, center, circles[0][2], cv::Scalar(0, 0, 255), 3, 8, 0);
-
-
setTimestamp(m_point3d);
-
m_point3dOut.write();
-
}
-
-
cv::imshow("Capture", receive);
-
cv::waitKey(1);
-
}
-
}
-
-
return RTC::RTC_OK;
-
}
-
1行目
OpenCVに必要なヘッダファイルをインクルードします。
-
2行目
色抽出などの関数を使用するためのヘッダファイルです。
-
4行目
色抽出に用いるHSVのしきい値を格納する構造体を用意します。
-
8-11行目
コンフィグレーションで設定したしきい値を先ほどの構造体に代入します。
-
18行目
Inactive状態のときにウィンドウを破壊します。
-
25-59行目
画像を取得した場合に、画像処理を行います。
・29-58行目
色抽出を行うので、ビット深度が24(カラー画像)のときに画像処理を行います。
・31行目
取得した画像をcv::Mat型の変数に格納します。
・32行目
color_extraction.cppに実装されているextract_color関数を使って色抽出を行い、
その結果をcv::Mat型の変数に格納します。
・34-35行目
色抽出した画像に対して円検出を行います。
・37-54行目
円が検出されている場合は処理を行います。
・41-43行目
検出した円の位置を計算します。
・49-50行目
検出した円の中心と、円の半径を描画します。
・52-53行目
タイムスタンプをセットし、ポートから出力します。
・56-57行目
取得した画像をウィンドウに表示します。
以上で、BallDetectionのコーディングは終了です。
コードが入力し終わったら、ビルドを行ってください。
BallDetection_greenのBallDetection.conf
3. TimedPoint3DConsoleOut RTC
TimedPoint3DConsoleOut RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
TimedPoint3DConsoleOut
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
CONSOLE
-
実行周期
1000
-
アクションコールバック
onInitialize
onExecute
-
データポート
・point3dポート
ポート名(InPort) point3d
データ型 TimedPoint3D
変数名 point3d
表示位置 LEFT
-
言語
C++
テンプレートを生成したらCMakeを行い、TimedPoint3DConsoleOut.cppファイルにコードを記述して下さい。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
-
RTC::ReturnCode_t TimedPoint3DConsoleOut::onExecute(RTC::UniqueId ec_id)
-
{
-
if(m_point3dIn.isNew())
-
{
-
m_point3dIn.read();
-
-
std::cout << "X: " << m_point3d.data.x
-
<< " Y: " << m_point3d.data.y
-
<< " Z: " << m_point3d.data.z << std::endl;
-
}
-
-
return RTC::RTC_OK;
-
}
コードの解説をします。
変数へのアクセス方法以外、ConsoleOutと同じであることがわかると思います。
-
3-10行目
Inポートに値が入力された場合、値を読み込みコンソールに表示します。
おさらいになりますが、TimedPoint3D型のアクセス方法は以下のようになります。
・m_<変数名>.data.x
・m_<変数名>.data.y
・m_<変数名>.data.z
以上で、TimedPoint3DConsoleOutのコーディングは終了です。
コードが入力し終わったら、ビルドを行ってください。
6. おわりに
単眼カメラを用いて、既知のカラーボールの位置を計測するRTCを作成しました。
複数の色を検出するため、同名のRTCを複数個実行し、位置を検出しています。
カラーボールを検出するためのしきい値はコンフィグレーションで設定できるようにしました。
また、カメラ画像の取得部分と画像処理部分を分けたことによりこのような構成が可能となっています。
コンフィグレーションやRTCの粒度に気を配り、RTCの再利用性をあげておくことの重要性がわかると思います。
自分のシステムを作るときには参考にしてみてください。

5.2 青のボールの検出


5.3 緑のボールの検出
5.4 赤のボールの検出

5.1 BallDetection RTCsの接続
. 実行環境の構築
今回は、青、緑、赤の3色カラーボールの位置を計測します。
そこで、Ball Detection RTCを3つ実行し、それぞれに各色のボールの位置を計測させます。
同名のRTCを複数実行する方法は、Defining Naming Formatsをご覧ください。
今回は以下のような環境を構築します。
-
BallDetectionRTCsフォルダ
-
WebCameraフォルダ
-
WebCameraComp.exe
-
WebCamera.conf
-
rtc.conf
-
-
TimedPoint3DConsoleOut
-
TimedPoint3DConsoleOutComp.exe
-
TimedPoint3DConsoleOut.conf
-
rtc.conf
-
-
BallDetection_blueフォルダ
-
BallDetectionComp.exe
-
BallDetection.conf
-
rtc.conf
-
-
BallDetection_greenフォルダ
-
BallDetectionComp.exe
-
BallDetection.conf
-
rtc.conf
-
-
BallDetection_redフォルダ
-
BallDetectionComp.exe
-
BallDetection.conf
-
rtc.conf
-
-
BallDetection RTCのコンフィグレーションファイルは以下のようになります。
各HSVのしきい値やカメラの内部パラメータは、使用するカラーボールやカメラに合わせて適せん変更してください。
BallDetection_blueのBallDetection.conf
-
exec_cxt.periodic.rate:30.0
-
naming.formats: %m_blue.rtc
-
-
configuration.active_config: mode0
-
-
conf.mode0.hue_lower: 90
-
conf.mode0.hue_upper: 110
-
conf.mode0.saturation: 180
-
conf.mode0.value: 30
-
conf.mode0.f_per_s: 636
-
conf.mode0.ball_radius: 10
5. 動作確認
作成したRTCを実行して下さい。
5.1図のように、WebCamera RTCを3つのBall Detection RTCに接続します。
Ball Detection RTCの出力をTimedPoint3DConsoleIn RTCに1つずつ接続して、物体の位置が出力されているか確認してください。
-
exec_cxt.periodic.rate:30.0
-
naming.formats: %m_green.rtc
-
-
configuration.active_config: mode0
-
-
conf.mode0.hue_lower: 50
-
conf.mode0.hue_upper: 80
-
conf.mode0.saturation: 50
-
conf.mode0.value: 130
-
conf.mode0.f_per_s: 636
-
conf.mode0.ball_radius: 10
BallDetection_redのBallDetection.conf
-
exec_cxt.periodic.rate:30.0
-
naming.formats: %m_red.rtc
-
-
configuration.active_config: mode0
-
-
conf.mode0.hue_lower: 175
-
conf.mode0.hue_upper: 5
-
conf.mode0.saturation: 240
-
conf.mode0.value: 110
-
conf.mode0.f_per_s: 636
-
conf.mode0.ball_radius: 10
図5.2-5.4のように、各色のカラーボールが検出されているのがわかります。
ぴったりではありませんが、カラーボールのおおよその位置を検出できることがわかります。
筆者の環境では円検出の揺らぎのため、たまに大きく外します が、おおよそZが ±5 cm程度で、X,Yは±2 cm程度の精度でした。