カメラの位置・姿勢は何に使うのか

経緯
OpenCV でカメラの位置・姿勢 ( 外部パラメータ ) を求めるには、
SolvePnP 関数や
SolvePnPRansac 関数を使用する。

だが、出力される回転ベクトル( rvec ) 並進ベクトル ( tvec ) をよく分かっていない。
カメラの位置・姿勢とかもよく分からん。ので調べ始めた。

 

画像からの三次元復元処理拡張現実感 ( AR ) のための位置合わせ処理において、
カメラの位置姿勢が必要となる。

 

三次元復元処理 ( 三次元再構成 )

三次元の物体をカメラで撮影すると、
二次元の画像になり三次元の情報が失われる

ステレオ写真のように一定の距離だけ離した二台のカメラを使用すると、
その場所から見た場合のみの三次元再生が可能。

ステレオ写真の原理を拡張して、
三次元物体を中心に多数の方向から写真を撮ると、
全ての方向から見た三次元物体が再生可能となる。

 

 

こちらから。
http://moitkfm.blogspot.jp/2014/06/2d-3d.html
http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html
http://ishidate.my.coocan.jp/opencv_17/opencv_17.htm

 

以上。
位置や姿勢の情報をどう使うかは放置しておく。よく分からないし。
姿勢というのも後回し。

C#_動的に作成したコントロールの判別 ( 追記 )

前に書いたコードの追記。
コントロー ルを格納したリストを使用したコード。前とほぼコード変わっていない。

 

ex )
ボタンをクリックすると、そのボタン .text に AAA が追記される。

    private int count = 0;
    private List<Button> buttonList = new List<Button>();

    private void buttonAdd_Click(object sender, EventArgs e)
    {
        int scrollValueY = panel1.VerticalScroll.Value;
        int scrollValueX = panel1.HorizontalScroll.Value;

        Button butoon = new Button();
        butoon.Location
            = new Point(10 - scrollValueX, 30 + (count * 40) - scrollValueY);
        butoon.Size = new Size(300, 19);
        butoon.Tag = count;
        butoon.Text = $"{count:D2}";
        butoon.Click += buttonNoShow_Click;
        panel1.Controls.Add(butoon);
        buttonList.Add(butoon);


        //Add ボタンを一番下に
        buttonAdd.Location
            = new Point(345 - scrollValueX, 30 + (count * 40) - scrollValueY);

        // スクロールバー位置設定
        int x = panel1.Width + scrollValueX;
        int y = panel1.Height + scrollValueY;
        panel1.AutoScrollPosition = new Point(x, y);

        ++count;
    }

    private void buttonNoShow_Click(object sender, EventArgs e)
    {
        int tagNum = (int)((Button)sender).Tag;
        buttonList[tagNum].Text = $"{tagNum:D2} AAA";
    }

buttonAdd の 345 はボタンの位置。不動。

 

以上

C#_動的に作成したコントロールの判別

前の続き。
判別するには、以下のコードを追記すればOK。

  • Control を配列に入れる
  • Control.Tag を使う。
  • object sender から Tag の値を取り出す


Control を入れた配列は ex) で使用していないが、
生成した複数の Control を取得して処理したい時は、配列に入れる必要あり。
例えば、生成した複数のテキストボックスに入力しあてる文字を
1 つのボタンを押して取得したい時など。※List はフィールドで定義。ex)コード間違えた。

 

ex)
生成ボタンを押したらそのボタン番号を表示。

    private int count = 0;

    private void buttonAdd_Click(object sender, EventArgs e)
    {
        int scrollValueY = panel1.VerticalScroll.Value;
        int scrollValueX = panel1.HorizontalScroll.Value;

        // ボタン作成
        List<Button> buttonList = new List<Button>();

        Button button = new Button();
        button.Location
            = new Point(10 - scrollValueX, 30 + (count * 40) - scrollValueY);
        button.Size = new Size(300, 19);
        button.Tag = count;
        button.Text = $"{count:D2}";
        button.Click += buttonNoShow_Click;
        panel1.Controls.Add(button);
        buttonList.Add(button);


        //Add ボタンを一番下に
        buttonAdd.Location
            = new Point(345 - scrollValueX, 30 + (count * 40) - scrollValueY);

        // スクロールバー位置設定
        int x = panel1.Width + scrollValueX;
        int y = panel1.Height + scrollValueY;
        panel1.AutoScrollPosition = new Point(x, y);

        ++count;
    }

    private void buttonNoShow_Click(object sender, EventArgs e)
    {
        var tagNum = ((Button)sender).Tag;
        MessageBox.Show($"{ tagNum }のボタンが押された");
    }

 

XXX_Event( object sender, EventArgs e )

 

sender

sender には発生元のオブジェクトが入っている
オブジェクトは クリックした Button などのこと。
Anchor や Dock 情報など、Button のプロパティ値が入っている。

 

sender は object なので、
Button 型 など発生元のオブジェクト型に変換して扱う

var tagNum = ((Button)sender).Tag;

 

tagNumobject 型。
int として取得したいなら、int 型に変換する。

int tagNum = (int)((Button)sender).Tag;

 

e

e にはイベントの補足情報
クリックしたマウスのボタン情報やクリックした座標などが入っている。

 

 

こちらから。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1168230276
https://dobon.net/vb/dotnet/control/buttonarray.html
http://tnomura9.exblog.jp/10713631/
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1357258528

 

以上。
イベントハンドラ
イベント発生した時に呼び出される処理のこと。

C#_プログラムから生成した ( 動的 ) コントロールにイベントをつける

デリゲートというものを標準ライブラリが使っている。
自分で デリゲート を定義する必要はなし。
delegate:代表、委譲、委託。メソッドを参照するための型。

 

Control.Click += 自作メソッド;

で実現できる。Control.Click標準ライブラリ
Click 以外にも MouseUpResize がある。
コントロー ルのイベントに対してデリゲートは用意されているっぽい

 

 ex )
Add ボタンをクリックするごとに、番号が記されたボタンが作成。
そのボタンを押すと「ボタンが押された」メッセージが出る。

    private int count = 0;

    private void buttonAdd_Click(object sender, EventArgs e)
    {
        int scrollValueY = panel1.VerticalScroll.Value;

        // ボタン 作成
        Button button = new Button();
        button.Location = new Point(10, 30 + (count * 40) - scrollValueY);
        button.Size = new Size(300, 19);
        button.Text = $"{count:D2}";
        button.Click += buttonNoShow_Click;
        panel1.Controls.Add(button);

        //Add ボタン
        buttonAdd.Location = new Point(345, 30 + (count * 40) - scrollValueY);

        // スクロールバー位置設定
        int x = panel1.AutoScrollPosition.X;
        int y = panel1.Height + scrollValueY;
        panel1.AutoScrollPosition = new Point(x, y);

        ++count;
    }


    private void buttonNoShow_Click(object sender, EventArgs e)
    {
        MessageBox.Show($"ボタンが押された");
    }

 

button.Click を定義まで辿ると、

public event EventHandler Click;
public delegate void EventHandler(object sender, EventArgs e);

 

試しに panel1.DragEnter というソースでも辿ると、

public event DragEventHandler DragEnter;
public delegate void DragEventHandler(object sender, DragEventArgs e);

 

 

動的に作成したコントロールの判別

上記のコードでは、押したボタンを判別できない。
判別するためには、

・Control を配列に入れる
Control.Tag を使う
object sender から Tag の値を取り出す

が必要。

ソースは次回持ち越し。

 

 

こちらから。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1374085798
http://www.r-nakai.com/archives/19

以上。

C#_デリゲートとは

動的コントロールにイベントつけようとしてデリゲートにつまづいた。

 

デリゲートはメソッドを参照するための型
クラスや構造体と同じ 1 つの型として扱われる。
delegate:代表、委譲、委託

 

A という名のメソッドと、 a というデリゲート型の変数があったとする。
aA; ということを実現するのがデリゲート。
デリゲートにより A メソッドを変数のように扱える。
他のメソッドに処理を丸投げするオブジェクト、というイメージ。
イベントが起きた時のイベントハンドリング ( 処理 ) を
どのメソッドに丸投げ ( 委託 ) するかを指示するためなどに使われる。

 

デリゲートを使用する為には、以下の様にデリゲート型を定義する。

delegate 戻り値の型 hogaMethod ( 引数 );

デリゲート型の変数には、デリゲートの定義時に指定したものと
    同じ戻り値の型引数をもつメソッドを代入することが出来る。

 ・デリゲートはクラスメソッド ( static ) と
    インスタンス ( 非static ) メソッドのどちらでも代入することが可。

ex)
hogaDelegate ( デリゲート ) を介して、ShowNum 関数を呼び出している。

    delegate void hogaDelegate(int x);

    private void button_Click(object sender, EventArgs e)
    {
        // hogaDelegate hogaD = ShowNum; とも書ける。
        hogaDelegate hogaD = new hogaDelegate(ShowNum);
        hogaD(100);
    }

    private void ShowNum(int x)
    {
        MessageBox.Show($"{x} を指定");
    }

hogaDelegate hogaD = ShowNum; は暗黙的hogaDelegate 型に変換している。

 

 デリゲートに複数のメソッドを代入

 += 演算子を用いることで、複数のメソッドを代入することが出来る

 複数のメソッドを代入した状態で、デリゲートの呼び出しを行うと、
代入した全てのメソッドが呼び出される。
複数のメソッドを格納した状態のデリゲートをマルチキャスト デリゲートという。
マルチ キャストデリゲート の呼び出しは +=代入した順
逐次実行される。並列実行はされない。

 

ex)
「100 を指定」「100 も指定」というメッセージボックスが表示される。

    private void button_Click(object sender, EventArgs e)
    {
        hogaDelegate hogaD = ShowNum;
        hogaD += ShowNumY;

        hogaD(100);
    }

    private void ShowNum(int x)
    {
        MessageBox.Show($"{x} を指定");
    }
    private void ShowNumY(int x)
    {
        MessageBox.Show($"{x} も指定");
    }

 

 

 以下、メモ程度

 

非同期呼出し

 BeginInvokeEndInvoke を使用する。

通常、メソッドを呼び出すとメソッド内の処理が完了するまで
呼び出し元には戻ってこない ( 同期呼出し )。

それに対して、メソッドを呼び出した瞬間に
呼び出し元に処理が戻ってくるような呼び出しを非同期呼出しという。

 

デリゲートの非同期呼出しをすると、
デリゲートを介して呼び出されるメソッドの処理と、
呼び出し元の処理が並行して行われる。 ( マルチスレッド ) 

 

ラムダ式

匿名関数をさらに簡便な記法で書けるようになった。
匿名関数:
メソッドをどこかに定義する必要があったが、直接、名前のないメソッドを記述できる仕組み。

C# 2.0 の記法
delegate(int n){ return n > 10; }

 

C# 3.0 の記法
(int n) => { return n > 10; }

ラムダ式の中身が return 文 1 つだけの場合には、{ } や return も省略できる。

 

 

こちらから。
http://ufcpp.net/study/csharp/sp_delegate.html

 

以上。

C#_自動でスクロールバーを一番下に設定 ( 追記 )

コントロー ルを追加していくプログラムにおいて、
追加後にスクロールバーを一番下に持ってくるソース。

 


動的コントロー ルの Location を 設定する時、
スクロール分引く必要あり

スクロールされた状態で ↓ コードを実行すると、

textBox.Location = new Point(10, 30 + (count * 40));

textBox の座標は指定した値にスクロール分が加算された値となる。

スクロールされた状態で panel上座標(10, 10)クリックした座標を取得した場合、
e.Location で取得した座標は スクロール分が加算されている。

 

ex)
スクロールバーを一番下に設定する。
Add ボンタン も下に移動。

    private int count = 0;

    private void buttonAdd_Click(object sender, EventArgs e)
    {
        int scrollValueY = panel1.VerticalScroll.Value;

        // textBox 生成
        TextBox textBox = new TextBox();
        textBox.Location = new Point(10, 30 + (count * 40) - scrollValueY);
        textBox.Size = new Size(300, 19);
        panel1.Controls.Add(textBox);

        //Add ボタンを一番下に
        buttonAdd.Location = new Point(345, 30 + (count * 40) - scrollValueY);

        // スクロールバー位置設定
        int x = panel1.AutoScrollPosition.X;
        int y = panel1.Height + scrollValueY;
        panel1.AutoScrollPosition = new Point(x, y);

        ++count;
    }

f:id:koshinRan:20171111162957p:plain

※ HorizontalScroll ( 水平スクロールバー ) は付かない前提のコード。
水平バーも考慮するなら、 HorizontalScroll を VeriticalScroll と同様に書く。

 

以上。

C#_プログラムからコントロールを追加 ( 動的に追加 )

 

panel.Controls.Add ( 追加コントロール ); を使用。
form にも追加可。

 

ex)
Add ボタンを押すごとに テキストボックスを 40 間隔で追加。

panel1 設置。AutoScroll:True 、 Dock:Fill 。

    private int count = 0;

    private void buttonAdd_Click(object sender, EventArgs e)
    {
        TextBox textBox = new TextBox();
        textBox.Location = new Point(10, 30 + (count * 40));
        textBox.Size = new Size(300, 19);
        panel1.Controls.Add(textBox);
        ++count;
    }

何故か作成したコントロールが panel の下に設置されてしまったら、
textBox.BringToFront();
を書く。

 

こちらから。
https://msdn.microsoft.com/ja-jp/library/0h5y8567(v=vs.110).aspx
http://ufcpp.net/study/csharp/lib_forms.html
http://www.atmarkit.co.jp/ait/articles/0505/13/news116.html

 

以上。
※ テキストボックスは100と設定しても自動で高さが19に。