環境設定 - OpenCV 2.4 & OpenCV 3.1 & OpenCV 2.2

OpenCV のビルドとインストール

 自分の環境には ROS Kinetic Kame を入れているので,すでに opencv3 のライブラリが一部インストールされている.ただ,開発を進めていくうえでバイナリパッケージのみでなくソースを見たくなる時があるので OpenCV2.4 と OpenCV3.1 をソースビルドしてローカルにインストールした.以下にその手順をまとめておく.(Graph Cut Stereo を試してみたかったので,あとから OpenCV2.2 もインストール.)

OpenCV ダウンロード

以下,ダウンロード先リンク.下記からほしいバージョンを選んでダウンロードする.
github.com

OpenCV Non Free モジュールのダウンロード

 一部新しいライブラリや特許で抑えられている特徴量の計算ライブラリ等は別のリポジトリで管理されているみたい.自分は必要になるので下記のリンク先からダウンロードした.
github.com

 自分は下記の 3 つのバージョンをダウンロードしてきた.

opencv-2.2
opencv-2.4.13
opencv-3.1.0
opencv_contrib-master

パッケージの解凍

$ cd ~/workspace/reps/
$ unzip opencv-2.4.13.zip
$ unzip opencv-3.1.0.zip
$ unzip opencv_contrib-master.zip
$ unzip opencv-2.2.zip

cmake の実行.(OpenCV2.2 は古いので,コンパイルを通すために変更が必要でした.詳しくは本エントリの最後を参照のこと.)

$ cd ~/workspace/reps/opencv-2.4.13
$ mkdir build install
$ cd build
$ cmake -D CMAKE_INSTALL_PREFIX=/home/koichi/workspace/reps/opencv-2.4.13/install -DBUILD_EXAMPLES=ON -DINSTALL_C_EXAMPLES=ON -DWITH_OPENGL=ON -DWITH_V4L=ON -DWITH_QT=ON ..
$
$ cd ~/workspace/reps/opencv-3.1.0
$ mkdir build install
$ cd build 
$ cmake -DCMAKE_INSTALL_PREFIX=../install -DBUILD_EXAMPLES=ON -DINSTALL_C_EXAMPLES=ON -DWITH_OPENGL=ON -DWITH_V4L=ON -DWITH_GSTREAMER=ON -DWITH_QT=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DWITH_CUDA=YES -DCUDA_GENERATION=Auto -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules/ ../opencv
make install -j8
$
$ cd ~/workspace/reps/opencv-2.2
$ mkdir build install
$ cmake -D CMAKE_INSTALL_PREFIX=/home/koichi/workspace/reps/opencv-2.2/install -DBUILD_EXAMPLES=ON -DINSTALL_C_EXAMPLES=ON -DWITH_OPENGL=ON -DWITH_V4L=ON -DWITH_QT=ON -DWITH_FFMPEG=OFF ..
$ 

ビルド & インストールの実行.

$ cd ~/workspace/reps/opencv-2.4.13/build
$ make install
$
$ cd ~/workspace/reps/opencv-3.1.0/build
$ make install
$ 
$ cd ~/workspace/reps/opencv-2.2/build
$ make install

上記のようにインストールすれば, "install/share/OpenCV" 配下に CMake の config ファイルが作成されるので, CMake を使ってビルドする場合はこの Config ファイルを指定してビルドすれば必要なパス等を読み込んでくれる.

OpenCV2.2 の変更点

    • 1. opencv-2.2/cvconfig.h.cmake

L22, L23 に下記を追記.

/* V4L/V4L2 capturing support via libv4l */ 
#cmakedefine HAVE_LIBV4L 
    • 2. opencv-2.2/modules/highgui/src/cap.cpp

L174 の下記の記述を削除し,代わりにその下の記述を追記する.

#if defined (HAVE_CAMV4L) || defined (HAVE_CAMV4L2) 
#if defined HAVE_LIBV4L || (defined (HAVE_CAMV4L) && defined (HAVE_CAMV4L2)) 
    • 3. opencv-2.2/modules/highgui/src/cap.cpp

削除 L227

#if !defined WIN32 && defined HAVE_CAMV4L && defined HAVE_CAMV4L2  

追記 L227

#if !defined WIN32 && defined HAVE_LIBV4L

追記 L244

#ifdef HAVE_CAMV4L

追記 L246, L247

#endif 
#ifdef HAVE_CAMV4L2

追記 L249

#endif
    • 4. opencv-2.2/modules/highgui/src/window_QT.cpp

削除 L308

usleep(1000);

追記 L308

struct timespec req;
req.tv_sec = (time_t)0;
req.tv_nsec = 1000000;
nanosleep(&req, NULL);
    • 5. opencv-2.2/modules/highgui/src/cap_v4l.cpp

削除 L217

#include <linux/videodev.h>

追記 L217

#include <libv4l1-videodev.h>

カメラキャリブレーション

 前回の投稿から一週間近くたってしまったが,今日はカメラのキャリブレーションを実施しようと思う.

V4L2 を使ったカメラコントロール

 キャリブレーションをする前に,カメラの設定をしないといけない.ピント,絞りやゲインの設定などである.設定可能なコントロールのリストを下記のコマンドで調べる.

hoge@hogepc:~$ v4l2-ctl -d /dev/videoLeftImgSrc --list-ctrls-menus

         brightness (int)    : min=0 max=4095 step=1 default=16 value=16
               gain (int)    : min=32 max=2047 step=1 default=32 value=32
  exposure_absolute (int)    : min=1 max=10000 step=1 default=333 value=10

上記パラメータで撮影した画像が下記の写真.全体的に暗く,露光時間を上げる必要がある.
f:id:rkoichi2001:20160522132041p:plain

露光時間を上げる設定を実施.

hoge@hogepc:~$ v4l2-ctl -d /dev/videoLeftImgSrc --set-ctrl=exposure_absolute=100

露光時間を上げたあとの写真.(テレビはさんまのまんま.今日のゲストは出川です.)
f:id:rkoichi2001:20160522132309p:plain

ROS を使ったカメラキャリブレーション

 ここからは,ROS と自作キャリブレーションボードを使ったカメラキャリブレーションを実施する.

キャリブレーションボードの作成

自作キャリブレーションには下記の chesspattern を使用.
http://opencv.jp/sample/pics/chesspattern_7x10.pdf

リンク先の資料は A4 サイズようになっているので,4倍に拡大して継ぎ接ぎすることで A2 サイズのボードを作成.作成後のボードは下記.
f:id:rkoichi2001:20160522133811p:plain

ROS キャリブレーションの実施

具体的な手順は下記を参照.
camera_calibration - ROS Wiki

ROS カメラのドライバノードを立ち上げる.

hoge@hogepc:~$ roslaunch usb_cam usb_cam_mod-test.launch

以下,起動 launch ファイル (usb_cam_mod-test.launch)

<launch>
  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="camera_name" value="videoLeftImgSrc" />
    <param name="video_device" value="/dev/videoLeftImgSrc" />
    <param name="image_width" value="1280" />
    <param name="image_height" value="960" />
    <!-- <param name="pixel_format" value="grey" /> -->
    <param name="pixel_format" value="bayer_grbg8" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="userptr"/>
    <param name="camera_info_url" value="file:///xxxx/usb_cam/launch/camera_info/videoLeftImgSrc_1280x960.yaml"/>
  </node>
  <node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
    <!--<remap from="image" to="/usb_cam/image_raw"/>-->
    <remap from="image" to="/usb_cam/image_raw"/>
    <param name="autosize" value="true" />
  </node>
</launch>

ROS camera_calibration ノードを立ち上げる.

hoge@hogepc:~$ rosrun camera_calibration cameracalibrator.py --size 10x7 --square 0.445 image:=/usb_cam/image_raw camera:=/usb_cam

上記コマンドを実行後,下記のキャリブレーション Window が立ち上がるので,画像内でボードをいろいろと動かしてサンプル数を増やす.適切にサンプル数を増やしていくことによって,右側のバーの値が上がっていく.最終的に,x, y, skew, size の 4 項目が全部緑になったらとりあえずキャリブレーション実行.
f:id:rkoichi2001:20160522140329p:plain


以下,キャリブレーション結果

[image]

width
1280

height
960

[narrow_stereo]

camera matrix
631.970382 0.000000 666.559439
0.000000 634.739853 507.227851
0.000000 0.000000 1.000000

distortion
-0.224393 0.036108 -0.002063 -0.002725 0.000000

rectification
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000

projection
434.929535 0.000000 666.586920 0.000000
0.000000 533.741333 514.566055 0.000000
0.000000 0.000000 1.000000 0.000000


上記結果を元に, camera_calibration ファイルを作成する.

hoge@hogepc:~$ gedit videoLeftImgSrc_1280x960.yaml
image_width: 1280
image_height: 960
camera_name: videoLeftImgSrc
camera_matrix:
  rows: 3
  cols: 3
  data: [631.970382, 0, 666.559439, 0, 634.739853, 507.227851, 0, 0, 1]
distortion_model: plumb_bob
distortion_coefficients:
  rows: 1
  cols: 5
  data: [-0.224393, 0.036108, -0.002063, -0.002725	, 0]
rectification_matrix:
  rows: 3
  cols: 3
  data: [1, 0, 0, 0, 1, 0, 0, 0, 1]
projection_matrix:
  rows: 3
  cols: 4
  data: [434.929535, 0, 666.586920, 0, 0, 533.741333, 514.566055, 0, 0, 0, 1, 0]

ROS キャリブレーション結果を用いて,画像の Undistort

作成した camera_calibration ファイルを使用して,画像の Rectification を実施.

カメラドライバノードの起動.

hoge@hogepc:~$ roslaunch usb_cam usb_cam_mod-test.launch

Rectification 画像作成ノードの起動.

hoge@hogepc:~$ ROS_NAMESPACE=usb_cam rosrun image_proc image_proc

Rectification 画像表示ノードの起動.

hoge@hogepc:~$ rosrun image_view image_view image:=/usb_cam/image_rect

Rectification 後の画像.画面端の窓枠が曲線から直線に治っていることがわかる.
(ただ,画面の本当に端の部分はまだ歪んでいるので,もう少し改善の余地があるのかも.)
f:id:rkoichi2001:20160522143431p:plain

環境設定 - ROS Kinetic Kame, PyCharm, Eclipse, git

 Ubuntu 14.04 をインストールして使うつもりだったので,ROS Indigo を使用していたが, Ubuntu 16.04 へのアップグレードに伴い ROS Kinetic Kame をインストールすることに.ROS Kinetic Kame 自体はまだベータ版リリースで,正直いろいろとはまりそうだったので,使用をためらっていたんだけど....

ROS のインストール

 インストール自体は,下記に沿ってやっていけばすんなり終わるかと.

http://wiki.ros.org/kinetic/Installation/Ubuntu

ROS のローカルワークスペースの作成

下記のように自分の ROS ワークスペースを作成した.

hogehoge@hogepc:~$ mkdir -p workspace/catkin_ws/src
hogehoge@hogepc:~$ cd ..
hogehoge@hogepc:~$ catkin_init_workspace

上記コマンドの実行で, catkin 用のワークスペースができる.ここで, devel フォルダに setup.bash ファイルが作られるので,これを.bashrc ファイルに追記しておくことで自分の ROS ワークスペースのパッケージ情報を ROS システムに伝えることができる.

hogehoge@hogepc:~$ gedit .bashrc

下記の一行を追記.

source ~/workspace/catkin_ws/devel/setup.bash

Python IDE PyCharm のインストール

 PythonIDE には,前から使っていた PyCharm をインストール.

PPA を追加する.

hogehoge@hogepc:~$ sudo add-apt-repository ppa:mystic-mirage/pycharm

システムパッケージキャッシュの更新.

hogehoge@hogepc:~$ sudo apt-get update

Pycharm-Community のインストール

hogehoge@hogepc:~$ sudo apt-get install pycharm-community

Eclipse のインストール

Eclipse のダウンロード

 使用する Eclipse には,最新の Mars を選択.
https://eclipse.org/downloads/

ダウンロードした圧縮ファイルを解凍し,移動.

hogehoge@hogepc:~$ tar zxvf eclipse-cpp-mars-2-linux-gtk-x86_64.tar.gz
hogehoge@hogepc:~$ sudo mv eclipse /opt/

eclipse 実行ファイルのパスを通す.

hogehoge@hogepc:~$ gedit .profile

上記のファイルの末尾に下記の一行を付け足すことでパスを通します.

PATH="$PATH:/opt/eclipse/eclipse"

Git のインストール

Git のインストールは apt-get install のみで完了.

$ sudo apt-get update
$ sudo apt-get install git

UBS カメラセッティング 2 - カメラ詳細情報の確認

 つくばチャレンジ 2015 に参加するにあたり,LSD SLAM を使ってやろうと思い下記のカメラを購入.かつステレオもやろうと思ったので 2 つ買った.(レンズ込みで1つ 9 万円 orz...) ここでは,まず OpenCV 等でカメラをいじる前に,簡単にカメラのサポートしている機能などを確認する方法をメモ.

www.theimagingsource.com

1. カメラビューアーのインストール

 兎にも角にも,イメージが見れないと困るので,下記のソフトウェアをインストール.おすすめのソフトは,"GTK UVC video viewer".こいつは Ubuntu Software Center からインストールできるので,素直にインストール.早速自宅実験場の様子をアップ(笑)

f:id:rkoichi2001:20160516015109p:plain

2. Video 4 Linux のインストール

 カメラの詳細情報や種々の設定をコマンドで実施するために,Video 4 Linux をインストール.

sudo apt-get install v4l-utils

3. カメラ情報の取得

 v4l-utils をインストールすることで,v4l2 の API をコマンドから叩くことが可能なる.まずは,カメラの情報を取得.

hogehoge:~$ v4l2-ctl -d /dev/videoLeftImgSrc --info

Driver Info (not using libv4l2):
	Driver name   : uvcvideo
	Card type     : DFK 23UM021
	Bus info      : usb-0000:00:14.0-3
	Driver version: 4.4.8
	Capabilities  : 0x84200001
		Video Capture
		Streaming
		Extended Pix Format
		Device Capabilities
	Device Caps   : 0x04200001
		Video Capture
		Streaming
		Extended Pix Format

4. 対応しているカメラフォーマットの取得

hogehoge:~$ v4l2-ctl -d /dev/videoLeftImgSrc --list-formats

ioctl: VIDIOC_ENUM_FMT
	Index       : 0
	Type        : Video Capture
	Pixel Format: 'GRBG'
	Name        : 8-bit Bayer GRGR/BGBG

	Index       : 1
	Type        : Video Capture
	Pixel Format: 'GREY'
	Name        : 8-bit Greyscale

	Index       : 2
	Type        : Video Capture
	Pixel Format: 'Y16 '
	Name        : 16-bit Greyscale

Ubuntu 14.04 に付いてくる v4l-utils では,GRBG の Pixel Format が対応してなかったみたいで,表示されなかった.このために,Ubuntu 16.04 をインストールすることを決断...

環境設定 Ubuntu 16.04

 11月に実施されるつくばチャレンジに向けて,開発環境のセットアップを実施したので,そのメモ.じつは,Ubuntu 16.04が出たばっかだったので,いろいろあると面倒だと思い,Ubuntu 14.04 で環境を構築したんだけど,いろいろとライブラリが古かったりなんやかんやあり,Ubuntu 16.04をインストールすることにした.下記,インストールの手順とその他設定を簡単にまとめておく.
(なんか,環境のセットアップばっかりに時間が取られてしまって,本質的なことに着手できてないなあ...)

Ubuntu 16.04 のインストール

 自分は Windows10 と Ubuntu 16.04 のデュアルブート環境にしてるんだけど,下記はその設定のやり方.

Ubuntu 16.04 のパーティションの切り方.

 自分の PC は HDD が2つついてて,片方 (sda) には Windows,もう片方 (sdb) には Ubuntu という構成になっている.sdbのパーティションは下記のように切った.

  • /dev/sda
    • /dev/sda1 (427MB) : Windows のリカバリ用領域, NTFS
    • /dev/sda2 (104MB) : Windows の boot 用領域, FAT32
    • /dev/sda3 (17MB) : Windows の Unknown 用領域
    • /dev/sda4 (17MB) : Windows のファイル領域, NTFS
  • /dev/sdb
    • /dev/sdb1 (255MB) : Boot 領域
    • /dev/sdb3 (498GB) : Ubuntu のファイル領域, Ext4
    • /dev/sdb2 (2.1GB) : Ubuntuスワップ領域, Linux Swap
    • /dev/sdb (1.1MB) : Unallocated な Space

システム全体のブート領域には /dev/sdb1 を選択.これで起動時には Grub が立ち上がり,WindowsUbuntu を選択できるようになった.

言語環境のインストール

 インストールした Ubuntu は日本語 Remix ではないので, Mozc をインストール.

Language Support 画面を開くと,必要なものを勝手にインストールしてくれる.

f:id:rkoichi2001:20160516012601p:plain

インストール完了後,再起動. Text Entry 画面を開き,"+" ボタンを押下して Japanese (Mozc) (IBus) を追加.

f:id:rkoichi2001:20160516012743p:plain

Synaptic Package Manager のインストール

 これは Ubuntu Software Center から "Synaptic Package Manager" を検索してインストールするだけ. Done!

Google Chrome のインストール

 Google Chromedeb パッケージをダウンロードしてインストールしたのだが,一部 Dependency をインストールしないとうまく行かず.下記,その手順を記載.

Chrome のダウンロード
$ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
必要な Dependency のインストール
$ sudo apt-get install libxss1 libgconf2-4 libappindicator1 libindicator7
Chrome のインストール & 再起動
$ sudo dpkg -i google-chrome-stable_current_amd64.deb

USBカメラセッティング 1 - デバイスの命名

GW 中に LSD SLAM を理解すべく,ガリ勉してなんとなく全体像は見えるようになったけど,到底手が入れられるレベルにはならず....このままだとロボット作成にめどがつかないとおもい...まずは簡単なところから手を動かして作業を始めることにしました.ということで,まずはカメラの ROS への取り込み.デバイスの名前を固定します.

1. 使用したいカメラを USB に接続する.

 兎にも角にも,使用したいデバイスを USB 接続します.この時,接続した HW の情報を確認する必要がありますが,"dmesg" コマンドを実行して必要な情報を抜き取ります.

以下,dmesg 実行時の情報.

[ 2049.485254] usb 3-3: USB disconnect, device number 3
[ 2075.682850] usb 3-3: new high-speed USB device number 5 using xhci_hcd
[ 2075.700782] usb 3-3: New USB device found, idVendor=199e, idProduct=8455
[ 2075.700792] usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2075.700797] usb 3-3: Product: DFK 23UM021
[ 2075.700801] usb 3-3: Manufacturer: The Imaging Source Europe GmbH
[ 2075.700804] usb 3-3: SerialNumber: xxxxxxxx
[ 2075.701511] uvcvideo: Unknown video format 47425247-0000-0010-8000-00aa00389b71
[ 2075.701527] uvcvideo: Found UVC 1.10 device DFK 23UM021 (199e:8455)

2. 使用するカメラのデバイス名の固定化

 通常,OpenCV や ROS で Image を取得する際には,デバイス名を指定する必要があります.この名前はデフォルトでは固定化されておらず,/dev/video0,/dev/video1 と言った形で接続した順番とうに依存して変わってしまいます.これでは困るので,ハードウェア枚にこの名前を固定してします.

変更するファイルは,"/etc/udev/rules.d/70-usb.rules" です.(名前は異なってもいいはずです.)
上記ファイルに,1 で取得したハードウェア固有の情報を記述していきます.

KERNEL=="video[0-9]*", MODE="0666", ATTRS{serial}=="xxxxxxx", SYMLINK+="videoRightImgSrc"

3. USB デバイスの抜き差し

 上記ファイルをセーブし,対象となる USB デバイスを抜き差しすれば,指定した名前でハードウェアが認識されているはずです.確認する方法は,"cd /dev" で dev フォルダに移動して,ls を実行して登録した名前のハードウェアがあれば完了です.





C# でのポインタの使用

C# ではポインタの使用は推奨されていないが,C/C++ コードとの連携や効率化のためにどうしても必要になることがある.このために,C# はいくつかの制限事項はありながらもポインタの使用を可能にしている.ここでは,C# で実際にポインタを使ってみる.

unsafe キーワード

C# にてポインタを使用する場合,「この範囲でポインタを使用します.」ということを明示的に宣言しなくてはいけない.この宣言を行うのが unsafe キーワードである.unsafe キーワードの実際の使用例は下記のとおり.

// 1. 関数の宣言時に.

[DllImport("", SetLastError=true)]
static extern unsafe bool ReadFile(int hFile, void* lpBuffer, int nBytesToRead, int* nBytesRead, int overlapped);

// 2. コードの決まったブロックの中で.

static void Main() {

  int num = 10;

  // Unsafe ブロック
  unsafe {
    int* p;
    p = &num;
    Console.Writeline("Address of Num : {0:X}", (UInt64)p);

  }
  return;
}

fixed キーワード

ポインタで変数を参照・更新するということは,対象となる変数がメモリ上の同じ場所にあることが保証されなくてはいけない.(勝手にアドレスが変わってしまうと困る.)しかしながら,.NET Framework では,ガーベッジコレクションが常にバックグラウンドで動いているために,知らず知らずのうちに対象となる変数・バッファのアドレスが変更されていることがありうる.これを防ぐために,C# では fixed キーワードを用いて対象となる変数を固定することができる.fixed キーワードによって明示的に宣言されたアドレスに関しては,ガーベッジコレクタはメモリを変更しない.
※ Fixed キーワードを用いて変数をメモリに固定化すると,一般的には .NET の効率を下げてしまう.そのため,本当に必要なときに,必要な場所で,できるだけ小さい範囲で fixed キーワードを用いるべきである.

  public unsafe int Read(byte[] buffer, int index, int count) {

    int bytesRead = 0;
    // Fixed スコープ
    // アドレスを取得したインスタンスは格納先のメモリ領域が移動・削除されなくなり,アドレスが変化しないことが保証される.
    fixed(byte* bytePointer = buffer) 
    {
      ReadFile(fileHandle, bytePointer + index, count, &bytesRead, 0);
    }
    return bytesRead;
  }