cv::Mat_ を使う場合の注意。
以前ここにあった記事は、見えなくしてあります。cv::Mat_
Povray を Fedora 18 にインストールする
Fedora 18 から、 povray が削除されてしまい、 そもそも Fedora には povray パッケージがなく
しかもサードパーティリポジトリにも Fedora 18 用がないので、自力でビルドしたい。
まず、 ATrpms にある src.rpm をダウンロードする。
$ wget http://dl.atrpms.net/all/povray-3.7.0.RC6-1.src.rpm
ただ残念なことに、 RC6 は Fedora 18 ではビルドできない。
POV-Ray のニューズグループの記事によると、 RC7 で修正されたらしいので、これで置き換える。
まず、 src.rpm をインストールする。
$ rpm -ivh povray-3.7.0.RC6-1.src.rpm
そうすると、 ~/rpmbuild/
以下に展開される。
~/rpmbuild/SOURCES/
に povray-3.7.0.RC6.tar.gz
があることが確認できる。ここに、 RC7 をダウンロードする。
$ wget http://www.povray.org/redirect/www.povray.org/beta/source/povray-3.7.0.RC7.tar.bz2
SPECS/povray.spec
の Version を RC7 に書き換え。あと、 .gz
となってる部分を .bz2
に書き換え。(ほんとは、ログとかちゃんと書いた方がいいと思う)。さらに、 40 行目がビルドの際にエラーになるので、削除 (頭に #
をつけてコメントアウト。)
で、ビルドする。 SPECS に移動して、
$ rpmbuild --bb --clean povray.spec
長いビルドの末、 RPMS/x86_64/povray-3.7.0.RC7-1.fc18.x86_64.rpm
がたぶん完成する。
誰もいらないと思うけど、 ここにこっそり置いておきます。
Windows 7 マシンを無線ルータ化する(アドホック接続)
- 有線でインターネッツできるようにする
- 「ネットワークと共有センター」を開く
- 「アダプターの設定の変更」をクリック(「ネットワーク接続」の画面になる)
- 今つながってる有線 LAN アダプタのプロパティを出す
- 「共有」タブで、「ネットワーク云々」という上段のチェックを押す
- 複数の無線アダプタがある場合は、どれにインターネット通信させるかを選ぶドロップダウンボックスが追加されている
- 2つ目のチェックボックスは任意
- この作業で、無線アダプタの IP アドレスが自動設定される(解除すれば、元に戻るらしい)
- このアドレスが、有線LANのほうのネットワークと同じだと都合が悪いので、変えないとならない。
- 「ネットワーク共有センター」を再び開く(履歴で戻ればいい)
- 「ワイヤレスネットワークの管理」をクリック
- 追加で、アドホックを追加する。
- そこで設定した暗号化とパスワードで、他の機器が接続できるようになる
- iPad1 だと、 WEP じゃないとつなげなかった。
- 通知領域のネットワークアイコンを開いて、「ユーザを待機しています」となっているときにつなぐ。
Fedora 18 での特殊キー設定
id:DOSEI:20120326:p1 に書いたことが、 Fedora 18 になったらできなくなってしまった。
Gnome3 のオーバレイ (アクティビティの画面?) を無効にすることができるらしい (前はハードコードされてるからできない、っていう話だった気がするが、改善されたのだろうか。)。
dconf-editor で、 org.gnome.mutter を開くと overlay-key という項目があり、デフォルトで Super-L がかかれているので、これを空文字列に変える。後は、 ibus-anthy の設定で Super-L に好きなものを割り当てればいい。
compose key についてはまだ調査中。
Tweak Tools (gnome-tweak-tool
) で同等の設定ができるようになっている。
通常の「設定」画面の「キーボード」の「ショートカット」タブの「タイピング」グループの「Compose キー」で compose キーを設定できる。参考
なす角
y 軸 (0,1,0) と適当なベクトル (a,b,c) のなす角をプログラムで求めるには、どの式を使えばより正確に求まるのだろうか。
- を
acos()
で計算- 小数で割り算して渡すので、精度の問題がある。
- [−1, 1] をはみ出すとエラーとなることに注意が必要。計算誤差でそうなることはよくあるのだが、いちいち
errno
でチェックするのはだるいので、std::max(-1.0, std::min(x, 1.0))
のように、クリップするとよい。
- を
atan2()
で計算- 分子・分母を別々に渡すので、関数がよきに計らってくれることが期待できる。
- (0, 0) でなければ、エラーにならない。
行列初期化の罠
プロローグ
よーしパパ、要素が 0 で初期化された行列つくっちゃうぞー
cv::Mat A(150, 100, CV_32S, 0); A.at<int>(20,10) = 30;
コンパイルも通ったし、バッチリだ!
エピローグ
セグフォー!
後日談
cv::Mat
のコンストラクタはたくさんあり、そのなかには値で初期化をするものがある。
cv::Mat::Mat(int rows, int cols, int type, const Scalar& s);
これが使われると思ってしまったのが敗因である。cv::Scalar
(の基の cv::Scalar_
) は、 int からの implicit なコンストラクタをもっているので、
cv::Mat A(150, 100, CV_32S, 20);
なら、問題なく 20 で初期化されると言う点がややこしい。では、なぜ 0 のときは何が起こっているのか。実は、 0 の時は、
cv::Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
が呼ばれている。つまり、 0 はヌルポインタと解釈されたわけである。この場合、 Mat は自動管理される領域の替わりに、ユーザが指定した領域を保持する。その結果、何も領域を持っていない Mat が出来上がり、要素にアクセスするとセグメンテーションフォルトとなる。
ちなみに、
cv::Mat::operator=(cv::Scalar)
も、全要素への値の代入を行うのだが、
A = 0;
は別の理由で拒否される。これは、 0 から暗黙に変換できる Mat を引数にとるオーバーロードもあるので、曖昧だと言われてしまう。このポインタを一つとるコンストラクタ
cv::Mat::Mat(const CvMat* m, bool copyData=false);
は、レガシーな型からの変換である。
もし、ゼロで初期化を指定したい場合は、
cv::Mat A(150, 100, CV_32S, cv::Scalar(0)); // by constructor A = cv::Scalar(0); // by operator=()
うーん。