2つの平面(領域)間の対応をとる方法。(C#で射影変換)





2つの平面(領域)間の対応をとる方法。(C#で射影変換)


お品書き

  • 2平面間の対応
  • 射影変換ってなんぞ
  • ライブラリ作った。(C# / .NET Standard2.0)
  • 可視化してみる
  • まとめ

2平面間の対応

はい。よくあると思います。

  • Canvas座標値と、そこの表示している地図画像の実世界上の値の対応(画素でnピクセルのところは実世界でmメートルなど)
  • 実世界平面上の値をUnityの空間に落とし込んだり

とか。かといって対応させたい領域が必ずしも綺麗な矩形ではなかったり、とか。
こういうタスクってたくさんあると思うのです。(みなさまどうしていらっしゃるのでしょう…)

そこで2平面間の対応を考えるのですが、射影変換とかいうのがあります。
画像処理だとよく使うのですが、画像処理以外にもいろいろと使えるので便利しています。

射影変換ってなんぞ。

射影変換の見た目は非常に簡単で、式はこんな感じです。

Hは3×3の行列で、9個のパラメータを持っています。
Pのx,yがもともとの平面上の座標、X,Yが変換後の座標です。Pに変換行列を書けると、もともとの平面上の座標を入れてかけると、出力の平面上の座標が得られる、というだけ。で、問題はこのHをどうやって求めるかなのかですが、これは入力平面と出力平面の対応点がそれぞれ4つあればHを推定することができます。この行列を推定する理屈の詳細はここでは省きますが、詳しくはこちら
こちらが分かりやすいと思います。

ライブラリ作った。(C# / .NET Standard2.0)

この変換行列を求める実装、C#からだとOpenCVSharpとかにあるにはあるんですけど、たかだか変換行列もとめるためだけに大きめのバイナリ突っ込まれるのもあれだし、ネイティブのdllが必要だったりするので良くないです。なので変換行列求めるためだけのクラスライブラリ作りました。nugetに登録してあるので

とか叩くと使えるようになるはず。

nuget->HomographySharp

GitHub->HomographySharp

行列計算はC#の行列演算ライブラリを使っています。
使い方は簡単で、入力平面の4点と出力平面の4点があれば良くて、

といった具合です。class HomographyHelperが二つのstatic関数、

  • 変換行列の推定を行う関数
  • 入力平面から出力平面上の座標に変換する関数

を持っている感じです。

可視化してみる。

といろいろ御託をなべても、実際にどういう風な変換をされるのか見てみないと信頼できないと思うので、可視化するプログラムも組みました。

GitHub->HomographySharp/HomographyVisualizer
4点の対応を取ると、動かしている点が、入力平面(最初に選んだ領域)の点が出力平面(あとに選んだ領域)と対応している様子が分かると思います。

まとめ

  • 2次元と2次元の座標の対応とるなら射影変換がそれなりに便利。
  • ライブラリっぽいものを作ってみた。
  • nugetにアップロードする実績を解放した。

関係ない独り言

可視化するプログラム、最近Rx勉強しているのでRxライクに書こうとしたけど…うーん。シンプルなストリームじゃなくて、イベントをIObservableにしてゴニョゴニョする、みたいのどーにも難しい。使いこなせればいろいろイベント登録して外して、みたいのしないで済みそうなだけに苦しい。(結局普通に書いた)(誰か氏私にRxを…)


neno

都内のJK大学生。趣味はドールと一緒にお出かけして撮影すること。C++とC#が好き。C++は主にリアルタイム画像処理, C#はUnity, WPF, UWP, .NET Coreとかいろいろ。ASPとXamarin学習中。 専攻はCV。最近のおもちゃはHoloLens。

あわせて読みたい

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

%d人のブロガーが「いいね」をつけました。