2014年12月13日土曜日
OpenCVでimreadが失敗するときは
Microsoft Visual Studio の 出力モードを Debug にしたうえで Release としてビルドされた OpenCV の cv::imread を使うと、内部で外側のライブラリか何かを読み込む処理が不味いらしく cv::imread から得られる Mat の data が NULL になる、つまり cv::imread が画像を読み込まない。解決法は出力モードを Release にするか OpenCV のビルドを Debug にするか、のどちらか。
//未試験ではあるがおよそOpenCVをDebugにしてVSをReleaseにしても似たような不具合が起こるかもしれない。
より子細にググりたい人向けに、私の用いた検索ワードは以下の通り
opencv imread debug
気付いた理由はただの勘。
参考になりそうなStackOverFlowの質問へのリンクを張っておく。
c++ - OpenCV imread(filename) fails in debug mode when using release libraries - Stack Overflow - http://stackoverflow.com/questions/9125817/opencv-imreadfilename-fails-in-debug-mode-when-using-release-libraries
--
ググってきた人向けに結論を先に書いておいた。以下は私の日記帳だ。
日記と混ざった技術系エントリを書いてくれる方がたまにいるが、結論にたどり着くまでに日記を読むのはつらいことが多い。誰があなたの食べたラーメンを知りたいのだろうか?技術の話を聞きに来たのに。
人のふり見てわがふり直すべきなので、ググってきた人には先に結論を。日記が読みたい人は日記を読めば良い。読む人がいない?日記帳というのはそういうものだ。
さて本題。久々にOpenCV。といっても最近はOpenCVでC++/C#なコードを息抜きに書くので、まあ10日ぶりくらいのOpenCV。
まあそんなわけでOpenCVでSURFでもやろうと思った。こいつは物体を認識してくれるすごいやつだ。詳しくはググったほうが私の説明より良いだろう。
今回、SURFを用いて、「探される画像」と「探したい画像」を使い、探される画像のどこらあたりに探したい画像が存在するかを検出したかった。
当然だがテストとしても、実際に動かすにしても、「探したい画像」くらいはどこかにあるファイルとして入力した方が良い。
そのために使えるのがOpenCVのimreadだ。こいつはパスを入れるだけで画像を読み込んでくれる。非常にシンプルだ。
で、まあ、結論に書いたとおりである。こいつが動作しなかった。
ReleaseとDebugのモードに原因があると気付いたのは完全に勘で、試しに動かしたらどうやら挙動が変わったので詳しくググってみたらそのようである、というStackOverFlowの記事等があった。'
ほかのメソッド類はきちんと動くので、実際わけがわからないが、まあとにかく内部のことなら仕方がないだろう。変えられない理由もあるはずだ(ないなら即座に変えてくれ。頼むから)。
そういうわけで、C++のdllがReleaseでコンパイルされていくことになった。OpenCVをDebugで再ビルドするのは手間なので、問題が起きるまではひとまずこれで進めていく。
最後に、せっかくの日記なので私が最近食べたラーメンについて記しておこう。
私は現在静岡県浜松市に住んでいるのだが、ここのつけ麺屋が最近のお気に入りだ。
麺喰いカケル (kakeru) - 遠州曳馬/ラーメン [食べログ] - http://tabelog.com/shizuoka/A2202/A220201/22026427/
私のオススメはさらっとした中華スープのほう。もちろん濃厚スープも美味しいが。
2014年12月7日日曜日
パッチワーク地形生成
というわけで本日の成果はこちら パッチワーク地形生成…とでもいうのだろうか いわゆるMinecraft特有の役割付けされた地形を生成したいと思った たとえばここで緑を平地として、薄青を丘とするといい具合に「それっぽく」見えると思う pic.twitter.com/7TuEDQt38s
— Takafumi Fukuyo (@TakafumiFukuyo) 2014, 12月 7
というわけでTwitterにこういったpostをした。
書ききれないところと、ソースコードの構成の解説をしたい。
ソースコードはgithubにアップロードしておいた。
https://github.com/TakafumiFukuyo/LookLikeTerrain/tree/master/ChildrenDraw
簡単に説明すると、ランダムウォークする4つの点(増加可能)が、既存の描画部分を上書きするか否かをランダムに決定しつつ、手持ちのペンの色(ランダム)とサイズ(固定)でキャンバス内を塗りつぶしていく。
キャンバスがすべて塗りつぶされたら終了である。
点は初期位置と最大到達可能距離、そして上書きするかどうかの毎ループごとの決定に使う値(powerと呼んでいる)を持っている。
1ループごとに、ランダムな角度と到達可能距離以内の範囲を極座標系でえらび、そこまでまっすぐに塗りつぶす(塗りつぶし可能であれば)。
ペンの情報は単純にintである。デバッグ用の描画関数がintをColorに変換してTexture2Dに入力している。
キャンバスの1単位分の情報が0のとき塗りつぶしていないと判定している。
単純にランダムにキャンバスを塗っていくだけなので、きまぐれな子供のような動きと思って名付けたのだが、これがなかなか面白い模様を作ってくれるように思える。
動かすまでまさかそんなうまく行くわけないと思っていたのだが。
このあとこのキャンバスの情報から塊の情報を得て、その塊に対して特定のアルゴリズムで地形を作る。
最後に地形の境界をなだらかにしてやれば、およそMinecraft風の「役割付けされた地形」のようなものができるように思える。
…ところでMinecraftの実際の地形生成はどうなっているのだろうか…。企業秘密というやつだろうか…。
2014年9月27日土曜日
S3Engine Unityについて(2) Slot,State,Signal,そしてFilterの概説
本記事の記述内容
Unity Game Engineにおけるフラグ管理ライブラリであるS3Engineの構造・実装についてと、またその理由について記す。
Signal
これはフラグ本体である。
フラグを変更するためのvoid Set(bool)と、それを簡便に行うためにvoid On(),void Off()がある。
フラグを読み込むためのbool Read()と読み込みをしたうえで変更をさせるbool DestructiveRead(bool)がある。
これについて異論のある人はいないだろう。
フラグを管理するのだからフラグの実態をしめすためのクラスを用いるのは自然だ。
同様にフラグを管理するのだから、一つの状態の変更とそれを示すこと、それ以外についてはクラスに表現されるべきではない。
なお、SignalとStateにはonTs,onFsという、それぞれOn時・Off時、あるいは状態がアクティブになった際と非アクティブにされる際に発動できるイベントハンドラのような構造があるが、これについては別のエントリで記すことにしたいと思う。
State
Signalとはフラグで、フラグとは状態を示すものである。Stateも状態を示すものである。なぜ二つは違う名前で違う機能を持たせられているか。
実は、すべてをSignalで行うことも可能である。Slotは単純にStateの集合のうちアクティブなものを集合内で一つに管理するだけだし、StateとSignalを関連付けるものは直接的にはなく、間接的なものですら必須ではないものがほとんどだ。
StateとSignalは単にプログラマがインスペクタ上での操作と視認を行いやすくするためにTransform上で親子関係にあるに過ぎない。
しかしながらこれはコードのレベルで見た問題だ。実際の開発はもっと複雑さを帯びているし、操作性と視認性が上がることは生産性に直結していく。
そして一番大事なのは、同じものを示すことができるとしても、表現の方法が違えば、扱う概念をより適切に示すことができるということだ。そのためにSignalは、StateのTransform子要素として配置することが推奨されるし、その配置表現から、StateはSignalより「よりまとまった」概念を示すのにうってつけだということだ。
Slot
Stateの項で説明した通り、Stateはまとまった状態を示す。まとまった状態は、状態によって表現を変えるゲーム上のものにとって、より大きな意味を持つものだ。たとえば歩くとか走るとか。
このまとまった状態を2つ以上同時に取ることは当然あり得ることではある。もちろんあり得るのだが、それは「まとまっていない状態」だとこのライブラリの設計上では捉えている。
つまり状態によって表現されるものがある時点で取れるまとまった状態はただ1つということだ。
この「ある1つの表現物が取れる状態が1つになる」また「表現物を違う状態にして、複数個置ける」ことを可能にするために、Stateをまとめる構造が要る。それがSlotだ。
と言っても、実際のコード上ではSlotは何の管理もしてくれない。Slotはただ、最初だと指示されたStateを、void Start()の呼ばれた時にアクティブにするだけだ。
Transform上でまとまっているというだけで、オブジェクト上ではまとまっているわけではないので当たり前と言えば当たり前だし、実際Stateを複数アクティブにすることもできる。それはライブラリユーザの自由だが、私は推奨しない。
そして、現実にState遷移時にStateのアクティブ・非アクティブを管理するのはFilterだ。
Filter
Signalは状態で、Stateはまとまった状態だと説明した。まとまった状態は、表現されるものにとって1つであることが推奨されることも説明した。
まとまった状態であるStateは1つである、つまり2つ以上のStateの間をアクティブだという情報が移動していくことになる。
そのアクティブ状態を移動させるための構造がFilterだ。
これは、特定のいくつかのSignalが、それぞれに対してライブラリユーザの任意の状態を取った時、現在のStateから目標のStateへアクティブ状態を移動する、という動作をする。
終わりに
簡単にS3 Engineのコア部分の説明をした。これらだけで最小限フラグと状態を表すことが可能だ。
今後はさらに、Signalをより柔軟かつ簡易に変更するためのユーティリティ群について説明していきたいと考えている。
2014年9月19日金曜日
S3 Engine Unityについて
簡単に1行で
Unity Game Engine(以下Unityと記す)におけるフラグ管理・状態管理ライブラリ
Unityにおけるフラグと状態の管理
基本的にユーザに任されているのが現状である。
Unityはシーンレベルまでの状態管理しか提供しない。そしてUnityのシーンローディングはそれなりに重量級の処理だ。
より小さなレベルでの状態管理、また、雑多になりやすいフラグ管理を適度な制御範囲(グローバル過ぎず、ローカル過ぎず)で提供することが必要だと考え、このライブラリを制作した。
愚直にフラグを管理した場合
シナリオ
Unityで、MonoBehaviourを継承したオリジナルな挙動をするクラスを作るとする。これがアタッチされたGameObjectをAlphaとする。
Alphaは単純に、Transformをz方向に進ませるだけのものである。
仕様変更があった。Alphaが一定以上進んだ際、別のGameObjectであるBetaを出現させることになった。
よって、Alphaに対し一定以上のzをfloatのインスタンスフィールドにて記述して、一定以上進んだら出現させ、出現済みフラグを立てる処理をした。
仕様変更があったAlphaがx方向にも動くようになった。GameObject Betaが出現済みで、かつx方向に一定以上進んだ際、別のGameObject Gammaを出現させるようにしたい。
同様にfloatにて一定以上のxをインスタンスフィールドにし、Betaの出現フラグを見つつxが一定以上かどうかを監視し、満たした際に新たにGammaを出現させ、出現済みフラグを立たせることにした。
問題点
処理が複雑に絡み合い過ぎている。
Alpha内部の毎フレームの処理が、ベタに、大量に、冗長に記述されている。
Betaの出現処理とGammmaの出現処理は、フラグのみによって関連しているだけなのに、1つのクラス内にあるのは不自然である。
今後も仕様変更が重なり、さらに複雑なGameObjectの出現手法が求められた際、対応が不可能になることが予測される。
シーングローバルなマネージャにてフラグを管理した場合
シナリオ
愚直なやり方はまずい、というわけで、フラグを、シーンレベルにグローバルな位置にあるManagerにて管理することにした。
このGameObjectのManagerクラスはbool値を大量に持ち、フラグ管理を任されている。
GameObject Alphaに対して、BetaEmergerというBetaを一定の条件で出現させるクラスが追加された。
同様にGammaEmergerも追加された。これらのEmergerクラスは、Managerへの参照を持ち、ここにあるフラグを読み込み・変更するものである。
仕様の追加があった。現在のAlphaの処理をそっくりそのまま、別のシーン(2つ目のシーン とする)でも動くようにしたいという要求が出た。
AlphaにはEmergerクラスがあり、これはManagerクラスを知る必要がある。
新たなシーンにAlphaとEmerger2つ、そしてManagerクラスを丸ごとPrefabでコピーした。
仕様の変更があった。最初にあったシーンとSecond SceneではAlphaは若干別の挙動をしたい。
Emergerを追加した。今までの処理にならい、Managerにフラグを追加した。
最初のシーンと2つ目のシーンにあるManagerは同じものだが、違う処理のために、不要なフラグを共有している状態になった。
問題点
このままいくとManagerクラスが肥大するだろう。
Managerクラスを分割したい場合、Emergerから、共通の型でManagerにアクセスできないため、ManagerごとにEmergerが必要になる。
Emergerを共通の処理にしたければ、interfaceでくくるほかないが、これではフラグ管理のためだけにやたらとコード数の肥大を招きかねない。
フラグはどの位置で管理されるべきか
上記した2つのシナリオから、インスタンスレベルでのフラグ管理も、シーングローバルレベルのフラグ管理も、どちらも問題点をはらんでいることがわかるだろう。
では、どの位置で管理されるべきか、だが、当然のごとくこの2つの中間層だ。
中間層とはどこか。Unityならば、Transformレベルでフラグは管理されるのが最も望ましい、となる。
Prefabレベルでのフラグ管理
シナリオ
基礎となるのはManagerクラスでの発想である。
問題点と、それに対してどのように対処するべきか、を以下に記す。
1.
Managerクラスは、すべてのフラグを一手に請け負おうとしたから破たんした。
特定のフラグのみを管理し、それ以外は管理しない、という姿勢でManagerクラスを変更するのが基本的な指針だろう。
2.
また、Managerクラスは内部にフラグの値(bool)を持っていた。
だが、本質的に見ればManagerは各クラスからのアクセスのためにフラグを保持しているのであって、保持する必要があるから保持しているのではない。各クラスからアクセスができれば何でもよい。
3.
さらに、Managerクラスは、別のシーンにクローンされ、シーンごとに細かなカスタムが加えられていったため、構造に破たんをきたした。
よって、Managerが管理するフラグは、十分に柔軟に変更されるデータ構造を持ち、型としてのフラグ一覧を持たないほうが良い。
まず1,2より、非常にシンプルなフラグのクラスを作ることが望ましいだろう。
なぜか。2.からわかる通り、フラグは、共有したい他の挙動の各所からアクセス可能であればそれで良い。
フラグクラスをMonoBehaviourから派生するものとし、1つのboolとそれへのアクセサを持つものとする。
これで、このMonoBehaviourの参照を各挙動に追加することで、フラグへの共有アクセスが可能になった。
さらに、3.の条件を満たしたい。これがなければフラグ管理部は肥大する。だがこれも、MonoBehaviourから派生したことで解決できる。
Unityには高度なオブジェクト階層システムがある。フラグひとつひとつをGameObjectとし、これらをTransform(自動で追加される)によるGame Object階層にて管理すればよい。これは十分に柔軟なデータ構造として働く。
S3 Engineにおける実装
上記した 非常にシンプルなフラグのクラス はSignalクラスとして実装されている。
また、フラグは、時として状態としても振る舞う。ゆえに、状態を示すクラスと、現在の状態をホールドするクラスが必要だと考えた。
これらを、StateクラスととSlotクラスとして実装した。
また、状態間を移動することを容易に、かつ安全にするためのFilterクラスを用意した。
Filterは、特定のSignalの条件を満たした際に、Slotのホールドする現在の状態を、目的の状態に移動させる。
余談だが、これらのSlot,State,Signalの頭文字を取ってS3 Engineと名付けた。
2014年9月18日木曜日
最初のpost
層や構造が好きで、いよいよ吐き出さなければ気が狂いそうになってきたのでここに書いていこうと思う。
文体が一定しないのはRubyを書いた後にC#を書くときにRuby風のcaseでメソッドや変数を書いてしまうようなもの(読者の方々も経験があると思う)なので、ゆるしてほしい。