Structure From Motion

SfMを勉強しようと思って、この本のChapter 4のソースコードを入手してビルドしようとしてはまったことのメモ。 動作ししてから思い出しながら書いているので抜けがあるかも。

Mastering OpenCV With Practical Computer Vision Projects: Step-by-step Tutorials to Solve Common Real-world Computer Vision Problems for Desktop or Mobile, from Augmented Reality and Number Plate Recognition

Mastering OpenCV With Practical Computer Vision Projects: Step-by-step Tutorials to Solve Common Real-world Computer Vision Problems for Desktop or Mobile, from Augmented Reality and Number Plate Recognition

  • 作者: Daniel Lelis Baggio,Shervin Emami,David Millan Escriva,Khvedchenia Ievgen,Naureen Mahmood
  • 出版社/メーカー: Packt Publishing
  • 発売日: 2012/12/03
  • メディア: ペーパーバック
  • この商品を含むブログ (2件) を見る

テキストに対応したソースコードはここから取得。 MasteringOpenCV/code · GitHub

PCLのビルド(実際にはびるどはしてないけど)

PCLの公式Siteでもall in one packageを用意しているが、 今回使用したVisual Studio 2013用がなかった。 1つ1つコンパイルするの嫌だなぁと思っていたら、VS2013用にall in one packageを作っている方が居たので、 Building Point Cloud Library with Visual Studio 2012/2013/2015 | Summary?Blog

SSBAのビルド

SSBAもビルド。下記を入手し、3rdparty\SSBA-3.0だけビルドして、 Chapter4_StructureFromMotion\3rdparty\SSBA-3.0 としてコピー。 royshil/SfM-Toy-Library · GitHub

SfMのcmake

cmakeで Chapter4_StructureFromMotion のVS2013用ソリューションファイルを作ろうとすると VTK_DIRがないと怒られる。エラーメッセージを見るとPCLのcmakeに書いてあるようなので、 インストールされているフォルダ構成に合わせて下記に修正。 "C:\Program Files (x86)\PCL 1.7.2\cmake\PCLConfig.cmake"

macro(find_VTK)
  if(PCL_ALL_IN_ONE_INSTALLER AND NOT ANDROID)
#    set(VTK_DIR "${PCL_ROOT}/3rdParty/VTK/lib/vtk-5.8")
    set(VTK_DIR "${PCL_ROOT}/3rdParty/VTK/lib/cmake/vtk-6.2")

SfMのビルド

やっと、VS2013用ソリューションファイルができたのでChapter4_StructureFromMotionのビルド。

  • SURFを使っているいくつかのファイルでエラーが出るので下記を追加。場所が移動しているらしい。
#include <opencv2/nonfree/gpu.hpp>
  • ↑と合わせて下記も追加。([ExploringSfMExec]->[プロパティ]->[構成プロパティ]->[リンカー]->[入力]->[追加の依存ファイル])  C:\opencv_2.4.11\opencv\build\x86\vc12\lib\opencv_nonfree2411.lib も追加()。

  • WIN32の手順でファイルを取得するらしいのだが、エラーが出るので下記を追加。 Common.cpp:

#include <windows.h>
  • 最後に異なるバージョンのopencvの混在でもはまった。  自分の環境には2.4.1をインストールしてたんだけど、opencv2.4.2~2.4.11を使うように指示されていたので、2.4.11をインストールした。 そうしたら、cv::imread()で落ちる。理由は、環境変数PATHに2.4.11へのパスより先に2.4.1のパスが書かれていたから。

DLT(Direct Linear Transformation:直接線形変換)

幾つか記事を見たり、文献を観たいしたけどいまいちわからなかったので整理。

特異値分解(SVD)を用いて最小二乗法によりHomographyを求める。

{\displaystyle x'_i=Hx_i}
明らかに
{\displaystyle x'_i \times Hx_i=0}
(これは |a| \times |a|=0 より明らか)
{\displaystyle
  H = 
  \left(
    \begin{array}{ccc}
      h_{11} & h_{12} & h_{13} \\
      h_{21} & h_{22} & h_{23} \\
      h_{31} & h_{32} & h_{33}
    \end{array}
  \right) = 
  \left(
    \begin{array}{ccc}
      h_1^{\mathrm{T}} \\
      h_2^{\mathrm{T}} \\
      h_3^{\mathrm{T}}
    \end{array}
  \right)
}
と置くと
{\displaystyle
  Hx_i = \left(
    \begin{array}{c}
      h_1^{\mathrm{T}} x_i\\
      h_2^{\mathrm{T}} x_i\\
      h_3^{\mathrm{T}} x_i
    \end{array}
  \right),
  x'_i = \left(
    \begin{array}{c}
      x'_i\\
      y'_i\\
      w'_i
    \end{array}
  \right)
}
よって、クロス積の定義より
{\displaystyle
x'_i \times Hx_i = \left(
    \begin{array}{cc}
      y'_i h_3^{\mathrm{T}} - w_i' h_2^{\mathrm{T}} x_i\\
      w'_i h_1^{\mathrm{T}} - x_i' h_3^{\mathrm{T}} x_i\\
      x'_i h_2^{\mathrm{T}} - y_i' h_1^{\mathrm{T}} x_i
    \end{array}
  \right) = 0
}
これを書き換えると
{\displaystyle
x'_i \times Hx_i = \left(
    \begin{array}{ccc}
      0^{\mathrm{T}}         & -w'_i x_i^{\mathrm{T}} &  y'_i x_i^{\mathrm{T}} \\
      w'_i x_i^{\mathrm{T}}  & 0^{\mathrm{T}}         & -x'_i x_i^{\mathrm{T}} \\
      -y'_i x_i^{\mathrm{T}} & x'_i x_i^{\mathrm{T}}  & 0^{\mathrm{T}}
    \end{array}
  \right) 
  \left(
    \begin{array}{c}
      h_1 \\
      h_2 \\
      h_3
    \end{array}
  \right) = 0
}
H はn倍しても等価なので最後の行は削除できる。
{\displaystyle x'_i} は同次座標系なので {\displaystyle w'_i=1}ととると
{\displaystyle
  \left(
    \begin{array}{ccccccccc}
      0   & 0   & 0   & -x_i & -y_i & -w_i &  y'_i x_i &  y'_i y_i &  y'_i w_i \\
      x_i & y_i & w_i & 0    & 0    & 0    & -x'_i x_i & -x'_i y_i & -x'_i w_i \\
    \end{array}
  \right) 
  \left(
    \begin{array}{c}
      h_1 \\
      h_2 \\
      h_3
    \end{array}
  \right) = 0
}
{\displaystyle w_i=1}と置く。また、各要素がゼロになるので符号をそろえて見やすくすると
{\displaystyle
  \left(
    \begin{array}{ccccccccc}
       0   &  0   &  0   & -x_i & -y_i & -1   &  y'_i x_i &  y'_i y_i &  y'_i w_i \\
      -x_i & -y_i & -1   & 0    & 0    & 0    &  x'_i x_i &  x'_i y_i &  x'_i w_i \\
    \end{array}
  \right) 
  \left(
    \begin{array}{c}
      h_{11} \\
      h_{12} \\
      h_{13} \\
      h_{21} \\
      h_{22} \\
      h_{23} \\
      h_{31} \\
      h_{32} \\
      h_{33} \\
    \end{array}
  \right) = 0
}
n個の座標を対象にすると下記のようにかける。
{\displaystyle
  \left(
    \begin{array}{ccccccccc}
       0   &  0   &  0   & -x_1 & -y_1 & -1   &  y'_1 x_1 &  y'_1 y_i &  y'_1 w_1 \\
      -x_1 & -y_1 & -1   & 0    & 0    & 0    &  x'_1 x_1 &  x'_1 y_i &  x'_1 w_1 \\
       0   &  0   &  0   & -x_2 & -y_2 & -2   &  y'_2 x_2 &  y'_2 y_2 &  y'_2 w_2 \\
      -x_2 & -y_2 & -1   & 0    & 0    & 0    &  x'_2 x_2 &  x'_2 y_2 &  x'_2 w_2 \\
           &      &      &      & \vdots
    \end{array}
  \right) 
  \left(
    \begin{array}{c}
      h_{11} \\
      h_{12} \\
      h_{13} \\
      h_{21} \\
      h_{22} \\
      h_{23} \\
      h_{31} \\
      h_{32} \\
      h_{33} \\
    \end{array}
  \right) = 0
}
{\displaystyle
Mx=0
}
これを特異値分解(SVD)を使って説く。
つづく。

参考:

Direct Linear Transform アルゴリズムを使って、投影変換の行列Hを計算する。 - ぱたヘネ
(ほぼこの記事に自分が読んでわからなかったところを書き足した感じ)

これなら分かる応用数学教室―最小二乗法からウェーブレットまで

これなら分かる応用数学教室―最小二乗法からウェーブレットまで

実践 コンピュータビジョン

実践 コンピュータビジョン

類似画像検索アルゴリズムの調査

類似画像検索というか下記要件を満たす検索をやりたい。

  • 画像は線画
  • 画像の中に特定の図形を探しだす
  • スケール、回転に不変(強い)
  • 探す先の画像は探し元の画像に対して非常に大きい

一から考えるのは無理があるので、適当なアルゴリズムを探している。

類似画像検索として一般的な分類としては

  • 特徴点ベース
  • テンプレートマッチング
  • ハフ変換とか

なんかがありそうなんだけどどういうのがいいことやら。

もう少し調べてみたらHuモーメントを使うのがよさそう。
Image moment - Wikipedia, the free encyclopedia
構造解析と形状ディスクリプタ — opencv 2.2 documentation

この路線で調べてみよう

RaspberryPiでLCDモニタ

aitendoの2.2インチTFT液晶をRasPiで使う - @SRCHACK.ORG(えす・あーる・しー・はっく)
を参考にやったがLCDでのコンソール表示が90度回転しなかったので、試した結果。

  • コンソールログインにする(GUIを立ち上げない)

/etc/inittab:

# The default runlevel.
id:2:initdefault:

#1:2345:respawn:/sbin/getty --noclear 38400 tty1
1:2345:respawn:/sbin/fbterm-login fb1 tty1

でランラベルを2に下げただけではだめだった。なぜ?

で、
rasp-config
を実行し
3 Enable Boot to Desktop/Scratch
Console Text console, requiring login (default)
を選択することで、LCDにログインプロンプトが出るようになったが、
90度回転していない。

/sbin/fbterm-login:

#!/bin/bash
# example: fbterm-login fb1 tty1
export FRAMEBUFFER=/dev/$1
exec /usr/bin/fbterm -r 1 --font-size=12 /bin/login < /dev/$2


/sbin/fbterm-login:

#!/bin/bash
# example: fbterm-login fb1 tty1
export FRAMEBUFFER=/dev/$1
exec /usr/bin/fbterm --screen-rotate=90 --font-size=12 /bin/login < /dev/$2

に修正したら90度回転するようになった(横長表示)

こっちで設定するのかと思っていたが、こちらはGUIのときに有効になるみたい。
/etc/modules:

# fbtft
fbtft_device name=adafruit22a rotate=90 speed=16000000

jQuery コードリーディング その2

まず、全体を俯瞰してみる。

  • ファイルサイズ:247KB
  • 総行数:9190行
  • 総文字数:247351文字

だいたい新聞朝刊二日分をくまなく読むくらいの量ですね。

では、読み始めます。
コメントは飛ばして15行目から。

(function( global, factory ) {

	if ( typeof module === "object" && typeof module.exports === "object" ) {
		// For CommonJS and CommonJS-like environments where a proper window is present,
		// execute the factory and get jQuery
		// For environments that do not inherently posses a window with a document
		// (such as Node.js), expose a jQuery-making factory as module.exports
		// This accentuates the need for the creation of a real window
		// e.g. var jQuery = require("jquery")(window);
		// See ticket #14549 for more info
		module.exports = global.document ?
			factory( global, true ) :
			function( w ) {
				if ( !w.document ) {
					throw new Error( "jQuery requires a window with a document" );
				}
				return factory( w );
			};
	} else {
		factory( global );
	}

// Pass this if window is not defined yet
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

// Can't do this because several apps including ASP.NET trace
// the stack via arguments.caller.callee and Firefox dies if
// you try to trace through "use strict" call chains. (#13335)
// Support: Firefox 18+
//

いきなりわからん。というか最初だからこそわからないのか。
そもそも

}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

の'{'に対応するカッコが見つからないんだが(viの % コマンドで探したが)...。
このコメントの意味がよく分からないけど、use strict をつけるとASP.NET, Firefoxでdieするのと関係あるの?よくわからん。もう少し、見てから戻ってきます。

// Can't do this because several apps including ASP.NET trace
// the stack via arguments.caller.callee and Firefox dies if
// you try to trace through "use strict" call chains. (#13335)
// Support: Firefox 18+
//

どんどんいこう。

var arr = [];

var slice = arr.slice;

var concat = arr.concat;

var push = arr.push;

var indexOf = arr.indexOf;

var class2type = {};

var toString = class2type.toString;

var hasOwn = class2type.hasOwnProperty;

var support = {};

arr で配列を準備。slice,concat,push,indexOfはarrのメソッドの対するエイリアス
class2type でプロパティを準備。プロパティは連想記憶(ハッシュ)と同じようなものだと理解している。toString, hasOwnはclass2typeのメソッドに対するエイリアス
support でプロパティを準備。

次回に続く。このペースでいくと何時終わるのやら。

jQuery コードリーディング その1

jQueryソースコードを読んで、
jQueryjavascriptを勉強する連載(予定)。
jQueryを使ったjavascriptプログラミングの勉強ではないです。

モチベーションはこれ

最近はオープンソースにもいいものがあります。例えば、jQueryは僕がMicrosoftの外に出てから、一番美しいと思ったコードですね。

ブログ主のプログラム関連スペックはこんな

  • Cはだいたいわかる
  • Railsはさわったことがある。Herokuで自分用に動かしている簡単なアプリがある。
  • javascriptは見よう見まねでコードを書いたことがある。生涯コード記述量は300行くらい。

jQueryのバージョンは現時点で最新の2.1.1を使う。

いつ終わるかわからないが、終わらせるまでやりたいと思う。