OpenRTM-aist-1.1-RELEASE, rtmtools-1.1.0-RC5, CMake, VC2010

はじめに

このケーススタディでは、簡単な画像処理をコンポーネント化する方法を紹介します。既存のカメラコンポーネントと画像表示コンポーネントを利用し、カメラからの画像を左右(または上下)に反転させる処理部分をコンポーネントとして作成してカメラの画像を反転させ表示するシステムを作成します。

画像を反転する処理は簡単に実装することができますが、ここではさらに簡単に実装するために OpenCV ライブラリを利用しより汎用性の高い RTコンポーネントを作成します。

OpenCVとは

OpenCV (オープンシーブイ) とはかつてインテルが、現在は Willow Garage が開発・公開しているオープンソースのコンピュータービジョン向けライブラリです。

Wikipediaより抜粋。

作成するRTコンポーネント

  • Flip コンポーネント: OpenCV ライブラリが提供する様々な画像処理関数のうち、cvFlip() 関数を用いて画像の反転を行う RTコンポーネント。

cvFlip 関数のRTコンポーネント化

入力された画像を左右または上下に反転し出力する RTコンポーネントを、OpenCV ライブラリの cvFlip 関数を利用して作成します。作成および実行環境は Windows上の Visual C++ を想定しています。対象 OpenRTM-aistのバージョンは 1.1.0 です。

作成手順はおおよそ以下のようになります。

  • 動作環境・開発環境についての確認
  • OpenCV と cvFlip 関数についての確認
  • コンポーネントの仕様を決める
    • データポート
    • コンフィギュレーション
  • RTCBuilder を用いたソースコードのひな形の作成
  • CMake を使ったプロジェクトの作成
  • ヘッダ、ソースの編集
    • アクティビティ処理の実装
    • ヘッダの編集
    • ソースの編集
  • CMakeを使ったインクルードパス・ライブラリパス・ライブラリの追加
  • コンポーネントの動作確認

動作環境・開発環境

ここで動作環境および開発環境を確認しておきます。

OpenRTM-aist-1.1 以降では、コンポーネントのビルドに CMake を使用します。また、RTC のひな形生成ツール RTCBuilder では、ドキュメントを入力してこれを Doxygen に処理させることで、コンポーネントのマニュアルも自動で生成することができるようになっており、このため CMake で Configure を行うときにDoxygen が要求されるため予めインストールしておく必要があります。

cvFlip 関数について

cvFlip 関数は、OpenCV で標準的に用いられている IplImage 型の画像データを垂直軸 (左右反転)、水平軸 (上下反転)、または両軸 (上下左右反転)に対して反転させます。関数プロトタイプと入出力の引数の意味は以下の通りです。

 void cvFlip(IplImage* src, IplImage* dst=NULL, int flipMode=0);
 #define cvMirror cvFlip
  
 src       入力配列
 dst       出力配列。もし dst = NULL であれば、src が上書きされます。
 flipMode 配列の反転方法の指定内容:
  flipMode = 0: X軸周りでの反転(上下反転)
  flipMode > 0: Y軸周りでの反転(左右反転)
  flipMode < 0: 両軸周りでの反転(上下左右反転)

コンポーネントの仕様

これから作成するコンポーネントを Flip コンポーネントと呼ぶことにします。

データポートの確認

このコンポーネントは画像データ型の入力ポート (InPort) と、反転処理した画像を出力するための出力ポート (OutPort) を持ちます。それぞれのポートの名前を 入力ポート (InPort)名: originalImage, 出力ポート(OutPort)名: flippedImage とします。

OpenRTM-aist には OpenCV を使用したビジョン関連のコンポーネントがサンプルとして付属しています。これらのコンポーネントのデータポートは画像の入出力に以下のような CameraImage 型を使用しています。

   struct CameraImage
     {
         /// Time stamp.
         Time tm;
         /// Image pixel width.
         unsigned short width;
         /// Image pixel height.
         unsigned short height;
         /// Bits per pixel.
         unsigned short bpp;
         /// Image format (e.g. bitmap, jpeg, etc.).
         string format;
         /// Scale factor for images, such as disparity maps,
         /// where the integer pixel value should be divided
         /// by this factor to get the real pixel value.
         double fDiv;
         /// Raw pixel data.
         sequence<octet> pixels;
     };

このFlipコンポーネントではこれらのサンプルコンポーネントとデータのやり取りができるよう同じくCameraImage型を InPort と OutPort に使用することにします。 CameraImage型は InterfaceDataTypes.idl で定義されており、C++であれば、InterfaceDataTypesSkel.h をインクルードすると使えるようになります。

コンフィギュレーションの確認

また、画像を反転させる方向は、左右反転、上下反転、上下左右反転の3通りがあります。これを実行時に指定できるように、RTコンポーネントのコンフィギュレーション機能を使用して指定できるようにします。 パラメーター名は flipMode という名前にします。

flipMode は cvFlip 関数の仕様に合わせて、型は int 型とし 上下反転、左右反転、上下左右反転それぞれに 0、1、-1 を割り当てることにします。

flipMode の各値での画像処理のイメージを下図に示します。

cvFlip_and_FlipRTC.png
Flip コンポーネントの flipMode 指定時の画像反転パターン

データポート・コンフィギュレーションの仕様まとめ

以上から Flip コンポーネントの仕様をまとめます。

コンポーネント名称 Flip
InPort
ポート名 originalImage
CameraImage
意味 入力画像
OutPort
ポート名 flippedImage
CameraImage
意味 反転された画像
Configuration
パラメータ名 flipMode
int
意味 反転モード
上下反転: 0
左右反転: 1
上下左右反転: -1

Flip コンポーネントの雛型の生成

Flipコンポーネントの雛型の生成は、RTCBuilderを用いて行います。

RTCBuilderの起動

Eclipseでは、各種作業を行うフォルダーを「ワークスペース」とよび、原則としてすべての生成物はこのフォルダーの下に保存されます。ワークスペースはアクセスできるフォルダーであれば、どこに作っても構いませんが、このチュートリアルでは以下のワークスペースを仮定します。

  • C:\rtcws

eclipse.exe をダブルクリックするとまず、ワークスペースの場所を尋ねられますので、上記のワークスペースを指定してください。 すると、以下のような「ようこそ」画面が表示されます。


fig1-1EclipseInit.png
Eclipseの初期起動時の画面

「ようこそ」画面は必要ないので左上の「×」ボタンをクリックして閉じてください。

fig2-2PerspectiveSwitch.png
パースペクティブの切り替え

右上の「Open Perspective」ボタンをクリックし、プルダウンの「Other…」を選択します。

fig2-3PerspectiveSelection.png
パースペクティブの選択

「RTC Builder」を選択することで、RTCBuilder が起動します。メニューバーに「カナヅチとRT」のRTCBuilderのアイコンが現れます。


新規プロジェクトの作成

Flip コンポーネントを作成するために、RTCBuilder で新規プロジェクトを作成する必要があります。プロジェクトを作成する方法は2種類あります。

  1. 画面上部のメニューから[ファイル] > [新規] > [プロジェクト]を選択 (Eclipse 共通)
    • 「新規プロジェクト」 画面において、[その他] > [RTCビルダ] を選択し、[次へ] をクリックします。
  2. メニューバーの「RTCBuilder」のアイコンをクリック
    fig2-5CreateProject.png
    RTC Builder 用プロジェクトの作成 1 (「ファイル」メニューから)

fig2-6CreateProject2.png
RTC Builder 用プロジェクトの作成 2(「ファイル」メニューから)

どちらの方法でも、次ようなプロジェクト作成ウィザードが開始されます。 「プロジェクト名」欄に作成するプロジェクト名 (ここでは Flip) を入力して [終了] をクリックします。

RT-Component-BuilderProject.png
RTC Builder 用プロジェクトの作成 3

指定した名称のプロジェクトが生成され、パッケージエクスプローラー内に追加されます。

PackageExplolrer.png
RTC Builder 用プロジェクトの作成 4

生成したプロジェクト内には、デフォルト値が設定された RTC プロファイル XML(RTC.xml) が自動的に生成されます。

RTC プロファイルエディタの起動

RTC.xmlが生成された時点で、このプロジェクトに関連付けられているワークスペースとして RTCBuilder のエディタが開くはずです。もし開かない場合は、ツールバーの [Open New RtcBuilder Editor] ボタンをクリックするか、メニューの [ファイル] > [Open New Builder Editor] を選択します。

Open_RTCBuilder.png
ツールバーから Open New RtcBuilder Editor

fig2-10FileMenuOpenNewBuilder.png
File メニューから Open New Builder Editor

プロファイル情報入力とコードの生成

まず、いちばん左の「基本」タブを選択し、基本情報を入力します。先ほど決めた Flip コンポーネントの仕様(名前)の他に、概要やバージョン等を入力してください。ラベルが赤字の項目は必須項目です。その他はデフォルトで構いません。

  • モジュール名: Flip
  • モジュール概要: Flip image component
  • バージョン: 1.0.0
  • ベンダ名: AIST
  • モジュールカテゴリ: Category
  • コンポーネント型: STATIC
  • アクティビティ型: PERIODIC
  • コンポーネント種類: DataFlowComponent
  • 最大インスタンス数: 1
  • 実行型: PeriodicExecutionContext
  • 実行周期: 60.0 (下図では1.0となってますが,60.0として下さい.)


Basic.png
基本情報の入力


次に、「アクティビティ」タブを選択し、使用するアクションコールバックを指定します。

Flip コンポーネントでは、onActivated()、onDeactivated()、onExecute() コールバックを使用します。下図のように①の onAtivated をクリック後に②のラジオボタンにて [ON] にチェックを入れます。 onDeactivated、onExecuteについても同様の操作を行います。


Activity.png
アクティビティコールバックの選択


さらに、「データポート」タブを選択し、データポートの情報を入力します。 先ほど決めた仕様を元に以下のように入力します。なお、変数名や表示位置はオプションで、そのままで結構です。


-InPort Profile:
    • ポート名: originalImage
    • データ型: CameraImage
    • 変数名: originalImage
    • 表示位置: left
      -OutPort Profile:
    • ポート名: flippedImage
    • データ型: CameraImage
    • 変数名: flippedImage
    • 表示位置: right


DataPort.png
データポート情報の入力


次に、「コンフィギュレーション」タブを選択し、先ほど決めた仕様を元に、Configuration の情報を入力します。制約条件および Widget とは、RTSystemEditor でコンポーネントのコンフィギュレーションパラメーターを表示する際に、スライダー、スピンボタン、ラジオボタンなど、GUIで値の変更を行うためのものです。

ここでは、flipMode が取りうる値は先ほど仕様を決めたときに、-1、0、1の3つの値のみ取ることにしたので、ラジオボタンを使用することにします。


-flipMode
    • 名称: flipMode
    • データ型: int
    • デフォルト値: 1
    • 変数名: flipMode
    • 制約条件: (-1, 0, 1) ※ (-1: 上下左右反転, 0: 上下反転, 1: 左右反転)
    • Widget: radio


Configuration.png
コンフィグレーション情報の入力


次に、「言語・環境」タブを選択し、プログラミング言語を選択します。ここでは、C++(言語)を選択します。なお、言語・環境はデフォルト等が設定されておらず、指定し忘れるとコード生成時にエラーになりますので、必ず言語の指定を行うようにしてください。

また、C++ の場合デフォルトでは CMake を利用してビルドすることになっていますが、旧式の VC のプロジェクトやソリューションを直接 RTCBuilder が生成する方法を利用したい場合は Use old build environment をチェックしてください。

Language.png
プログラミング言語の選択


最後に、「基本」タブにある [コード生成] ボタンをクリックし、コンポーネントの雛型を生成します。


Generate.png
雛型の生成(Generate)


※ 生成されるコード群は、eclipse起動時に指定したワークスペースフォルダの中に生成されます。現在のワークスペースは、[ファイル] > [ワークスペースの切り替え]」で確認することができます。

仮ビルド

さて、ここまででFlipコンポーネントのソースコードが生成されました。 処理の中身は実装されていないので、InPort に画像を入力しても何も出力されませんが、生成直後のソースコードだけでもコンパイルおよび実行はできます。

※サービスポートとプロバイダを持つコンポーネントの場合、実装を行わないとビルドが通らないものもあります。

では、まず CMake を利用してビルド環境の Configure を行います。Linux であれば、Flip コンポーネントのソースが生成されたディレクトリーで

 $ cmake .
 $ make

とすれば、Configure およびビルドが完了するはずです。

Windows の場合は GUI を利用して Configure してみます。 スタートメニューなどから CMake (cmake-gui) を起動します。

CMakeGUI0.png
CMake GUI の起動とディレクトリーの指定

画面上部に以下のようなテキストボックスがありますので、それぞれソースコードの場所 (CMakeList.txt がある場所) と、ビルドディレクトリーを指定します。

  • Where is the soruce code
  • Where to build the binaries

ソースコードの場所は Flip コンポーネントのソースが生成された場所で CMakeList.txt が存在するディレクトリーです。デフォルトでは <ワークスペースディレクトリー>/Flip になります。

Eclipse の画面左側、パッケージエクスプローラーの Flip 直下の CMakeLists.txt を CMake GUIの Where is the soruce code のテキストボックスにドラッグアンドドロップするのが一番手っ取り早いでしょう。

ProjectToCMake.png
CMakeLists.txtの指定

ビルドディレクトリーとは、ビルドするためのプロジェクトファイルやオブジェクトファイル、バイナリを格納する場所のことです。場所は任意ですが、この場合 <ワークスペースディレクトリー>/Flip/build のように分かりやすい名前をつけた Flip のサブディレクトリーを指定することをお勧めします。

Where is the soruce code C:\rtcws\Flip
Where to build the binaries C:\rtcws\Flip\build

指定したら、下の [Configure] ボタンをクリックします。すると下図のようなダイアログが表示されますので、生成したいプロジェクトの種類を指定します。 今回はVisual Studio 10 とします。VS8 や VS9 を利用している方はそれぞれ読み替えてください。また、プロジェクトのタイプには 32bit と 64bit も選択できる場合がありますので、自分がインストールしている OpenRTM-aist に合わせて選択してください。

CMakeGUI1.png
生成するプロジェクトの種類の指定

ダイアログで [Finish] をクリックすると Configure が始まります。問題がなければ下部のログウインドウに Configuring done と出力されますので、続けて Generate ボタンをクリックします。Generating doneと出力されればプロジェクトファイル・ソリューションファイル等の出力が完了します。

なお、CMake は Configure の段階でキャッシュファイルを生成しますので、トラブルなどで設定を変更したり環境を変更した場合は [ファイル] > [Delete Cache] でキャッシュを削除して Configure からやり直してください。

次に先ほど指定した build ディレクトリーの中の Flip.sln をダブルクリックして Visual Studio 2010 を起動します。

起動後、ソリューションエクスプローラーの ALL_BUILD を右クリックしし ビルド を選択してビルドします。特に問題がなければ正常にビルドが終了します。

VCbuild0.png
ビルド画面

ヘッダ、ソースの編集

ヘッダ (include/Flip/Flip.h) およびソースコード (src/Flip.cpp) をそれぞれ編集します。 Eclipse 画面左のパッケージエクスプローラーでそれぞれのファイルをダブルクリックすると、通常は Visual C++ の編集画面が開きますので、そこで編集します。Eclipse の中央のエディタにドラッグアンドドロップしても編集できます。

アクティビティ処理の実装

Flip コンポーネントでは、InPort から受け取った画像を画像保存用バッファに保存し、その保存した画像を OpenCV の cvFlip() 関数にて変換します。その後、変換された画像を OutPort から送信します。


onActivated(),onExecute(),onDeactivated()での処理内容を下図に示します。

FlipRTC_State.png
アクティビティ処理の概要


onExecute()での処理を下図に示します。


FlipRTC.png
onExucete()での処理内容


ヘッダファイル (Flip.h) の編集

OpenCV のライブラリを使用するため、OpenCV のインクルードファイルをインクルードします。

 //OpenCV 用インクルードファイルのインクルード
 #include <cv.h>
 #include <cxcore.h>
 #include <highgui.h>

この cvFlip コンポーネントでは、画像領域の確保、Flip 処理、確保した画像領域の解放のそれぞれの処理を行います。これらの処理は、それぞれ onActivated()、onDeactivated()、onExecute() のコールバック関数にて行います。

   /***
    *
    * The activated action (Active state entry action)
    * former rtc_active_entry()
    *
    * @param ec_id target ExecutionContext Id
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
   virtual RTC::ReturnCode_t onActivated(RTC::UniqueId ec_id);
 
   /***
    *
    * The deactivated action (Active state exit action)
    * former rtc_active_exit()
    *
    * @param ec_id target ExecutionContext Id
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
   virtual RTC::ReturnCode_t onDeactivated(RTC::UniqueId ec_id);
 
   /***
    *
    * The execution action that is invoked periodically
    * former rtc_active_do()
    *
    * @param ec_id target ExecutionContext Id
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
   virtual RTC::ReturnCode_t onExecute(RTC::UniqueId ec_id);

反転した画像の保存用にメンバー変数を追加します。

   IplImage* m_imageBuff;
   IplImage* m_flipImageBuff;

ソースファイル (Flip.cpp) の編集

下記のように、onActivated(),onDeactivated(),onExecute()を実装します。

 RTC::ReturnCode_t Flip::onActivated(RTC::UniqueId ec_id)
 {
   // イメージ用メモリの初期化
   m_imageBuff = NULL;
   m_flipImageBuff = NULL;
 
   // OutPort の画面サイズの初期化
   m_flippedImage.width = 0;
   m_flippedImage.height = 0;
  
   return RTC::RTC_OK;
 }
 
 
 RTC::ReturnCode_t Flip::onDeactivated(RTC::UniqueId ec_id)
 {
   if(m_imageBuff != NULL)
   {
     // イメージ用メモリの解放
     cvReleaseImage(&m_imageBuff);
     cvReleaseImage(&m_flipImageBuff);
   }
 
   return RTC::RTC_OK;
 }
 
 
 RTC::ReturnCode_t Flip::onExecute(RTC::UniqueId ec_id)
 {
   // 新しいデータのチェック
   if (m_originalImageIn.isNew()) {
     // InPortデータの読み込み
     m_originalImageIn.read();
 
     // InPort と OutPort の画面サイズ処理およびイメージ用メモリーの確保
     if( m_originalImage.width != m_flippedImage.width || m_originalImage.height != m_flippedImage.height)
       {
     m_flippedImage.width = m_originalImage.width;
     m_flippedImage.height = m_originalImage.height;
 
     // InPort のイメージサイズが変更された場合
     if(m_imageBuff != NULL)
       {
         cvReleaseImage(&m_imageBuff);
         cvReleaseImage(&m_flipImageBuff);
       }
 
     // イメージ用メモリーの確保
     m_imageBuff = cvCreateImage(cvSize(m_originalImage.width, m_originalImage.height), IPL_DEPTH_8U, 3);
     m_flipImageBuff = cvCreateImage(cvSize(m_originalImage.width, m_originalImage.height), IPL_DEPTH_8U, 3);
       }
 
     // InPort の画像データを IplImage の imageData にコピー
     memcpy(m_imageBuff->imageData,(void *)&(m_originalImage.pixels[0]),m_originalImage.pixels.length());
 
     // InPort からの画像データを反転する。 m_flipMode 0: X軸周り(左右反転), 1: Y軸周り(上下反転), -1: 両方の軸周り(上下左右反転)
     cvFlip(m_imageBuff, m_flipImageBuff, m_flipMode);
 
     // 画像データのサイズ取得
     int len = m_flipImageBuff->nChannels * m_flipImageBuff->width * m_flipImageBuff->height;
     m_flippedImage.pixels.length(len);
 
     // 反転した画像データを OutPort にコピー
     memcpy((void *)&(m_flippedImage.pixels[0]),m_flipImageBuff->imageData,len);
 
     // 反転した画像データを OutPort から出力する。
     m_flippedImageOut.write();
   }
 
   return RTC::RTC_OK;
 }

CMake によるビルドに必要なファイルの生成

CMakeList.txt の編集

Eclipse 画面左のパッケージエクスプローラーで src/CMakeLists.txt をダブルクリックorエディタへドラッグアンドドロップして編集します。

EditCmakeLists.png
CMakeLists.txtの編集

このコンポーネントでは OpenCV を利用していますので、OpenCV のヘッダのインクルードパス、ライブラリやライブラリサーチパスを与えてやる必要があります。幸い OpenCV は CMake に対応しており、以下の2行を追加・変更するだけで OpenCV のライブラリがリンクされ使えるようになります。

  • src/CMakeLists.txt を修正する
    • Eclipse のパッケージエクスプローラーで src/CMakeLists.txt をダブルクリック
  • find_package(OpenCV REQUIRED)を追加
  • 二つのtarget_link_libraries に ${OpenCV_LIBS} を追加
    • target_link_libraries は2ヶ所あり、上が DLL、下が実行ファイルのライブラリ指定です

 set(comp_srcs Flip.cpp )
 set(standalone_srcs FlipComp.cpp)
 
 find_package(OpenCV REQUIRED) ←この行を追加
   :中略
 add_dependencies(${PROJECT_NAME_LOWER} ALL_IDL_TGT)
 target_link_libraries(${PROJECT_NAME_LOWER} ${OPENRTM_LIBRARIES} ${OpenCV_LIBS}) ← 47行目と51行目にOepnCV_LIBSを追加

VC++ によるビルド

ビルドの実行

CMakeList.txt を編集したので、再度 CMake GUI で Configure および Generate を行います。 CMake の Generate が正常に終了した事を確認し、Flip.sln ファイルをダブルクリックし、Visual C++ 2010 を起動します。

Visual C++ 2010 の起動後、下図のようにし、コンポーネントのビルドを行います。


VC++_build.png
ビルドの実行


Flip コンポーネントの動作確認

ここでは、OpenRTM-aist-1.1 以降で同梱されるようになったカメラコンポーネント (OpenCVCameraComp、または DirectShowCamComp)とビューアコンポーネント (CameraViewerComp)を接続し動作確認を行います。

NameService の起動

コンポーネントの参照を登録するためのネームサービスを起動します。


[スタート] > [すべてのプログラム] > [OpenRTM-aist1.1] > [C++] > [tools] から「Start Naming Service」をクリックしてください。

&color(RED){※ 「Start Naming Service」をクリックしても omniNames が起動されない場合は、フルコンピューター名が14文字以内に設定されているかを確認してください。

rtc.confの作成

RTコンポーネントでは、ネームサーバーのアドレスやネームサーバーへの登録フォーマットなどの情報を rtc.conf というファイルで指定する必要があります。

下記の内容を rtc.conf というファイル名で保存し、Flip\FlipComp\Debug(もしくは、Release)フォルダーに置いてください。

※ Eclipse 起動時に workspace をデフォルトのままにしていた場合、Flip フォルダーのパスは、

C:\Documents and Settings\<ログインユーザー名>\workspace となります。

 corba.nameservers: localhost
 naming.formats: %n.rtc

Flip コンポーネントの起動

Flip コンポーネントを起動します。

先程 rtc.conf ファイルを置いたフォルダーにある、FlipComp.exe ファイルを実行してください。

カメラコンポーネントとビューアコンポーネントの起動

USBカメラのキャプチャ画像を OutPort から出力する OpenCVCameraComp,、または DirectShowCamComp コンポーネントと、InPort で受け取った画像を画面に表示する CameraViewerComp を起動します。

これら2つのコンポーネントは、下記の手順にて起動できます。

[スタート] > [すべてのプログラム] > [OpenRTM-aist1.1] > [components] > [C++] > [examples] > [opencv-rtcs] から、「OpenCVCameraComp」と「CameraViewerComp」をそれぞれクリックして実行します。

OpenCVCameraComp ではうまくカメラを認識しない場合があります。その場合は DirectShowCamComp を使用してみてください。

コンポーネントの接続

下図のように、RTSystemEditor にてOpenCVCameraComp (または DirectShowcomp) と Flip、CameraviewerComp コンポーネントを接続します。

RTSE_Connect.png
コンポーネントの接続

コンポーネントの Activate

RTSystemEditor の上部にあります「ALL」というアイコンをクリックし、全てのコンポーネントをアクティブ化します。正常にアクティベートされた場合、下図のように黄緑色でコンポーネントが表示されます。


RTSE_Activate.png
コンポーネントのアクティブ化


動作確認

下図のようにコンフィギュレーションビューにてコンフィギュレーションを変更することができます。

Flip コンポーネントのコンフィギュレーションパラメーター「flipMode」を「0」や「-1」などに変更し、画像の反転が行われるかを確認してください。


RTSE_Configuration.png
コンフィギュレーションパラメーターの変更


Flip コンポーネントの全ソース

Flip コンポーネントソースファイル (Flip.cpp)

 // -*- C++ -*-
 /*!
  * @file  Flip.cpp
  * @brief Flip image component
  * @date $Date$
  *
  * $Id$
  */
 
 #include "Flip.h"
 
 // Module specification
 static const char* flip_spec[] =
   {
     "implementation_id", "Flip",
     "type_name",         "Flip",
     "description",       "Flip image component",
     "version",           "1.0.0",
     "vendor",            "AIST",
     "category",          "Category",
     "activity_type",     "PERIODIC",
     "kind",              "DataFlowComponent",
     "max_instance",      "1",
     "language",          "C++",
     "lang_type",         "compile",
     // Configuration variables
     "conf.default.flipMode", "1",
     // Widget
     "conf.__widget__.flipMode", "radio",
     // Constraints
     "conf.__constraints__.flip_mode", "(-1,0,1)",
     ""
   };
 
 /*!
  * @brief constructor
  * @param manager Maneger Object
  */
 Flip::Flip(RTC::Manager* manager)
   : RTC::DataFlowComponentBase(manager),
     m_originalImageIn("originalImage", m_originalImage),
     m_flippedImageOut("flippedImage", m_flippedImage)
 {
 }
 
 /*!
  * @brief destructor
  */
 Flip::~Flip()
 {
 }
 
 
 RTC::ReturnCode_t Flip::onInitialize()
 {
   // Registration: InPort/OutPort/Service
   // Set InPort buffers
   addInPort("originalImage", m_originalImageIn);
   
   // Set OutPort buffer
   addOutPort("flippedImage", m_flippedImageOut);
   
   // Bind variables and configuration variable
   bindParameter("flipMode", m_flipMode, "1");
 
   return RTC::RTC_OK;
 }
 
 
 RTC::ReturnCode_t Flip::onActivated(RTC::UniqueId ec_id)
 {
   // イメージ用メモリーの初期化
   m_imageBuff = NULL;
   m_flipImageBuff = NULL;
 
   // OutPort の画面サイズの初期化
   m_flippedImage.width = 0;
   m_flippedImage.height = 0;
  
   return RTC::RTC_OK;
 }
 
 
 RTC::ReturnCode_t Flip::onDeactivated(RTC::UniqueId ec_id)
 {
   if(m_imageBuff != NULL)
   {
     // イメージ用メモリーの解放
     cvReleaseImage(&m_imageBuff);
     cvReleaseImage(&m_flipImageBuff);
   }
 
   return RTC::RTC_OK;
 }
 
 
 RTC::ReturnCode_t Flip::onExecute(RTC::UniqueId ec_id)
 {
   // 新しいデータのチェック
   if (m_originalImageIn.isNew()) {
     // InPortデータの読み込み
     m_originalImageIn.read();
 
     // InPort と OutPort の画面サイズ処理およびイメージ用メモリーの確保
     if( m_originalImage.width != m_flippedImage.width || m_originalImage.height != m_flippedImage.height)
       {
     m_flippedImage.width = m_originalImage.width;
     m_flippedImage.height = m_originalImage.height;
 
     // InPort のイメージサイズが変更された場合
     if(m_imageBuff != NULL)
       {
         cvReleaseImage(&m_imageBuff);
         cvReleaseImage(&m_flipImageBuff);
       }
 
     // イメージ用メモリーの確保
     m_imageBuff = cvCreateImage(cvSize(m_originalImage.width, m_originalImage.height), IPL_DEPTH_8U, 3);
     m_flipImageBuff = cvCreateImage(cvSize(m_originalImage.width, m_originalImage.height), IPL_DEPTH_8U, 3);
       }
 
     // InPort の画像データを IplImage の imageData にコピー
     memcpy(m_imageBuff->imageData,(void *)&(m_originalImage.pixels[0]),m_originalImage.pixels.length());
 
     // InPort からの画像データを反転する。 m_flipMode 0: X軸周り, 1: Y軸周り, -1: 両方の軸周り
     cvFlip(m_imageBuff, m_flipImageBuff, m_flipMode);
 
     // 画像データのサイズ取得
     int len = m_flipImageBuff->nChannels * m_flipImageBuff->width * m_flipImageBuff->height;
     m_flippedImage.pixels.length(len);
 
     // 反転した画像データを OutPort にコピー
     memcpy((void *)&(m_flippedImage.pixels[0]),m_flipImageBuff->imageData,len);
 
     // 反転した画像データを OutPort から出力する。
     m_flippedImageOut.write();
   }
 
   return RTC::RTC_OK;
 }
 
 
 extern "C"
 {
  
   void FlipInit(RTC::Manager* manager)
   {
     coil::Properties profile(flip_spec);
     manager->registerFactory(profile,
                              RTC::Create<Flip>,
                              RTC::Delete<Flip>);
   }
   
 };

Flip コンポーネントのヘッダファイル (Flip.h)

 // -*- C++ -*-
 /*!
  * @file  Flip.h
  * @brief Flip image component
  * @date  $Date$
  *
  * $Id$
  */
 
 #ifndef FLIP_H
 #define FLIP_H
 
 #include <rtm/Manager.h>
 #include <rtm/DataFlowComponentBase.h>
 #include <rtm/CorbaPort.h>
 #include <rtm/DataInPort.h>
 #include <rtm/DataOutPort.h>
 #include <rtm/idl/BasicDataTypeSkel.h>
 #include <rtm/idl/ExtendedDataTypesSkel.h>
 #include <rtm/idl/InterfaceDataTypesSkel.h>
 
 //OpenCV 用インクルードファイルのインクルード
 #include<cv.h>
 #include<cxcore.h>
 #include<highgui.h>
 
 using namespace RTC;
 
 /*!
  * @class Flip
  * @brief Flip image component
  *
  */
 class Flip
   : public RTC::DataFlowComponentBase
 {
  public:
   /*!
    * @brief constructor
    * @param manager Maneger Object
    */
   Flip(RTC::Manager* manager);
 
   /*!
    * @brief destructor
    */
   ~Flip();
 
   /***
    *
    * The initialize action (on CREATED->ALIVE transition)
    * formaer rtc_init_entry() 
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
    virtual RTC::ReturnCode_t onInitialize();
 
   /***
    *
    * The activated action (Active state entry action)
    * former rtc_active_entry()
    *
    * @param ec_id target ExecutionContext Id
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
    virtual RTC::ReturnCode_t onActivated(RTC::UniqueId ec_id);
 
   /***
    *
    * The deactivated action (Active state exit action)
    * former rtc_active_exit()
    *
    * @param ec_id target ExecutionContext Id
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
    virtual RTC::ReturnCode_t onDeactivated(RTC::UniqueId ec_id);
 
   /***
    *
    * The execution action that is invoked periodically
    * former rtc_active_do()
    *
    * @param ec_id target ExecutionContext Id
    *
    * @return RTC::ReturnCode_t
    * 
    * 
    */
    virtual RTC::ReturnCode_t onExecute(RTC::UniqueId ec_id);
 
  protected:
   // Configuration variable declaration
   /*!
    * 
    * - Name:  flipMode
    * - DefaultValue: 1
    */
   int m_flipMode;
 
   // DataInPort declaration
   CameraImage m_originalImage;
 
   /*!
    */
   InPort<CameraImage> m_originalImageIn;
   
   // DataOutPort declaration
   CameraImage m_flippedImage;
 
   /*!
    */
   OutPort<CameraImage> m_flippedImageOut;
 
  private:
   // 処理画像用バッファ
   IplImage* m_imageBuff;
   IplImage* m_flipImageBuff;
 };
 
 
 extern "C"
 {
   DLL_EXPORT void FlipInit(RTC::Manager* manager);
 };
 
 #endif // FLIP_H

Flip コンポーネントの全ソースコード

Flip コンポーネントの全ソースコードを以下に添付します。

Flip.zip

ダウンロード

最新バージョン : 2.0.1-RELESE

統計

Webサイト統計
ユーザ数:2159
プロジェクト統計
RTコンポーネント307
RTミドルウエア35
ツール22
文書・仕様書2

Choreonoid

モーションエディタ/シミュレータ

OpenHRP3

動力学シミュレータ

OpenRTP

統合開発プラットフォーム

産総研RTC集

産総研が提供するRTC集

TORK

東京オープンソースロボティクス協会

DAQ-Middleware

ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク