質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1114閲覧

アフィン変換の行列の適用

stdnium

総合スコア15

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2018/01/12 04:46

###前提・実現したいこと
アフィン変換を適用した画像の特徴点マッチングプログラムを作成したいのですが、
行列の適用方法がわかりません。

###発生している問題・エラーメッセージ
行列をどう適応するのか不明。

###該当のソースコード

C++

1// 変換なし、同じ画像サイズの二枚の画像を特徴点マッチングさせる自作プログラム 2// ズレ量を算出しマッチングプログラムを評価 3 4/* 省略 */ 5/* 特徴点抽出、特徴量記述にはSIFTを使用 6keypoint1,keypoint2はimg1,img2のkeypoint群 7match1[i]はi個目のマッチングにおけるkeypoint1内の番号 8match2[i] 同上 */ 9 10double erx, ery, error; 11 12 for (int i = 0; i < count; i++) { 13 cout << i << " : " << "key1の" << match1[i] << "個目とkey2の" << match2[i] << "個目がマッチング" << endl; 14 15 // ピクセルの大小比較・ずれ計算 16 erx = keypoint1.at(match1[i]).pt.x - keypoint2.at(match2[i]).pt.x; 17 if (erx < 0) erx *= -1; 18 ery = keypoint1.at(match1[i]).pt.y - keypoint2.at(match2[i]).pt.y; 19 if (ery < 0) ery *= -1; 20 error = erx + ery; 21 22 cout << "key1の座標" << keypoint1.at(match1[i]).pt << "key2の座標" << keypoint2.at(match2[i]).pt << endl; 23 cout << "ズレ量は" << error << "pixel" << endl; 24 25 } 26 27/* 省略 */

###補足情報(言語/FW/ツール等のバージョンなど)
・VisualStudio2017
・openCV3.3.0

http://www.robots.ox.ac.uk/~vgg/research/affine/
上記サイトのViewPointの画像の使用を検討しています。

解凍した「Viewpoint>H1to2p」フォルダ内に
8.7976964e-01 3.1245438e-01 -3.9430589e+01
-1.8389418e-01 9.3847198e-01 1.5315784e+02
1.9641425e-04 -1.6015275e-05 1.0000000e+00
という3x3の行列(?)の記述がありましたが、これをどう適用すればよいかわかりません。(恐らく「Viewpoint>img1」、「Viewpoint>img2」の変換に関係する行列だと思います)

数学的知識が乏しいため、申し訳ありませんが解説を頂けたら嬉しいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

アフィン変換は空間上の座標を別の座標への拡大縮小・回転・剪断・移動の変換を行列との乗算により行う手法で図形を取り扱う場面ではよく出てきます。数学が不得意といってもこうしたものを扱う限りは最小限勉強しておくべきと思います。「アフィン変換」「行列演算」などでどんな演算をするか確認しておくのは必要だと思います。

基本的に2次元座標の変換を用いる場合、変換マトリックスは3x3とし、変換座標を[x, y, 1]というベクトルであると考えて変換マトリックスとベクトルの乗算を行います。しかし計算機上での実現の仕方には若干のバリエーションがあります。システムによって変換に用いる方向(ベクトルを右からかけるか、左からかけるか)やあるいは(同じことですが)行列の表現方法などが微妙に変わってきたりします。

  • 左右の違い

結果=行列xベクトル
結果=ベクトルx行列

  • マトリックスの表現方法

m00, m01, m02
m10, m11, m12,
m20, m21, m22
だったり
m00, m10, m20,
m01, m11, m21,
m02, m12, m22
あるいは拡大がない場合は
m00, m01, m02
m10, m11, m12,
0, 0, 1
となるので、3行目を省略した2x3の要素で変換を表現したり・・・etc.


なお、ご質問にある行列をそのまんま3x3の変換行列と見做して右からベクトルをかけたときと左からベクトルをかけたときの変換結果は次の図のようになります。元の座標は原点を中心とした一辺が100の黒の四角形です。

(A)結果座標 = 変換マトリックス x 変換元座標
イメージ説明
(B)結果座標 = 変換元座標 x 変換マトリックス
イメージ説明

単なる想像ですが、題材から(B)の計算が前提ではないかと推測します。

C++

1float matrix[3][3] = { { 8.7976964e-01, 3.1245438e-01, -3.9430589e+01}, ... }; 2 3// resultの最初の要素がx, 次の要素がy 4 5void affineTransform(float x, float y, float* result) { 6 float p[3] = { x, y, 1 }; 7 for (int i = 0; i < 2; i++) { 8 result[i] = 0; 9 for (int j = 0; j < 3; j++) { 10 result[i] += p[i] * matrix[j][i]; 11 } 12 } 13}

上記のコードではresult[2]の計算を省略していますが、実際計算してみるとほぼ1になるので、おそらくこの変換は拡大・縮小を伴わない変換なのだろうと思います。

投稿2018/01/12 05:45

編集2018/01/18 12:34
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

stdnium

2018/01/18 12:19

ご回答ありがとうございました。 行列による画像の変換がイメージし辛かったため、大変勉強になりました。 これを機に数学の勉強もしなければと思いました。
guest

0

回答済みですが参考に。

###アフィン変換とは二次元平面または三次元空間における点を移動させる処理ためのものです。

もちろん、単純にベクトルの加減算や定数倍をするだけでも点の移動は実現できます。

###しかし、アフィン変換の重要なところは、正方行列の乗算だけでこれを実現しようというところにあります。

高校程度の数学の知識があれば難しくないと思いますが、「図形を原点周りに回転する」だとか、「図形を原点中心に拡大縮小する」という変換は正方行列の乗算だけで簡単に実現できます。一方で、平行移動を実現しようとすると簡単にはできません。

###そこでベクトルの次元を一次元余分に用意します。
平面であれば(x, y ,1)、立体であれば(x, y, z, 1)という感じに表現します。こうすると平行移動を正方行列の乗算で実現することができます。さらに、原点中心の回転や拡大縮小と組み合わせることで、任意の点を中心とした回転や拡大縮小が実現できます。

###なぜ正方行列の乗算だけでこれを実現したいのか
このような疑問を持つかもしれません。おそらく、「次数をあげてまで乗算に拘らなくても、平行移動だけベクトル加減算でいいではないか?」とお思いでしょう。

###行列の乗算だけで全ての座業変換を表現することには大きな価値があります。
コンピュータグラフィックスの世界では、変換対象の図形の数は非常に膨大です。このため、全ての図形に共通して計算できる部分は一度に済ませてしまいたい要望があります。

###ここから先はもう初等的な算数の問題です。
加減算と乗算が複雑に入り乱れた計算は、適切な順番で計算しないことには正しい答えにたどり着けません。したがって、式の最後がわかるまで途中計算ができません。一方、すべてが乗算であれば式の途中まで先に計算することができます。したがって、膨大な図形を移動させるうえでは、乗算だけで変換を実現することが非常に有効な手段となります。共通部分をまとめて計算しておいておけるからです。

投稿2018/01/18 13:16

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問