ホーム > Tips

Tipsのアーカイブ

.NET Framework on Raspberry Pi

MonoとMonoDevelopがRaspberryPiで動くことを確認した。
latest kernelを使っていると、Hard-float ABI絡みのバグでMonoが起動しないが、公式ページからダウンロードできるSoft-float版を使うと難なく起動できた。
WinFormsのプロパティコントロールとか、重そうなGUIが難なく動くのは感動する。動作はそりゃあ遅いが、そのへんは使い方次第。

ついでに、自分がRaspberry Piにしている設定をメモしておく。

  • Setup Wireless LAN driver

たいてい、まずは無線LAN化したい。すべてはこの方が書いてくれている。
しかも、PlanexのUS-GW MicroNというUSB無線LANアダプタは秋葉原で300円で叩き売られてたのを以前まとめ買いしたので、家にありました。
ドライバを登録したら、wicdをインストールしてさくっと無線LANパスワードなどを設定できます。もちろんAuto-Connectにしとく。固定IPにしとくとあとで色々楽。
いまどき有線LANとHDMIディスプレイが同じ所には無いので、最初に無線化しておけばディスプレイやテレビの裏に放置して作業できる。

  • Setup on-screen keyboard

いちいちキーボードをつなぐのは面倒なので、matchbox-keyboardをインストールしてマウスのみで操作できるように。
sudo apt-get install matchbox-keyboard するだけ。

  • X11vncを自動起動させる

そうこうしていると、PCからRaspberryPiを操作したくなってくる。メインのPCでぐぐってコピペしたいときとか。
x11vncを入れると、HDMIで表示している画面をリモートから操作できる。
自動起動するようにしておけば、電源だけ入れてRaspberryPi本体をどっかに放置しとけば、母艦PCからいじれる。
本家のBBSに自動起動の方法がある。.desktopファイルを作るのがポイント。
http://www.raspberrypi.org/phpBB3/viewtopic.php?p=108862#p108862

  • Display sizeを変更する

VNCで接続すると、ワイド大画面で優秀さをアピールしてくるRaspberryPiちゃんを、適度な画面サイズに調教する。/boot/config.txtのframebuffer_widthとheightを800*600ぐらいにしておく。

  • Synaptic

GUIでSearchしながらいろいろInstallしたい。sudo apt-get install synapticしておくと、普通に使える。

  • 日本語Fontのインストールとlocaleの変更

ttf-takaoなど、日本語フォントをSynapticでインストールしてから、sudo raspi-configでlocaleを変更する。フォントを先に入れないと文字化けする。

このへんまでやっとけば、あとはいろいろなアプリケーションを入れて遊べると思う。
ついでのつもりが、Raspberry Pi初期設定がメインになってしまった。。

App Inventor for Androidがヤバい

Androidもいじってみとかないとな、と思って、色々開発環境をインストールした。
調べてみると、クロスプラットフォームな開発環境が多くてびっくり。Linuxじゃ無理っぽいのはUnityぐらいだった。
開発環境はクロスプラットフォームで、WindowsもMacもLinuxも動くものが多いんだけど、対象デバイスをクロスプラットフォーム=iPhoneでもAndroidでもソースレベルでは互換性があるようにしようとすると、選択肢は少ない。あたりまえだけど。
結局、Titaniumなんかは両方(開発環境がクロスプラットフォーム&対象OSがクロスプラットフォーム)を満たしているっぽいんだけど、まだ手を付けていない。
なぜかというと、最初に手を付けたApp Inventorが楽しいから。

App Inventorは、もともとGoogle Labsで公開されていた、Visual Programming環境で、今はGoogle Labsの閉鎖に伴ってMITに移っている。まあ画面キャプチャとかはググれば出てくる。
Visual programmingというとPdやMAXやScilabのScicosやMATLABのSimulinkなど、先で繋いでくものが思いつく。いや思いつく人少ないか。ちなみにオープンソースを先に挙げてるのはわざとね。
App Inventorは、Visualといっても、ソースコードそのまんま箱に入れただけみたいな構造。先に挙げた配線系のやつらはプログラミングいらず!とか言って宣伝できるけど、App Inventorはプログラミングじゃん!というかんじ。だと思った。
ぶっちゃけ配線するスタイルはコード書くのが普通な人には馴染めないところがあると思うんだけど、その点逆にわかりやすかった。

わかりやすすぎて、音声認識でTweetしてみようと思って、実機テストするまで1時間ぐらいだった気がする。
ログインボタンでTwitterコンポーネントを用いたログイン、音声認識ボタンで音声認識コンポーネントを用いて音声認識、あとは確定ボタンとTweetボタンをちょこっと書くだけ。

GPSとかのセンサ情報を得たり、SMSでメッセージを送ったりもコンポーネントが用意されていて一瞬でできる。ヤバい。
とくに携帯アプリとかって、簡単な構造でも便利な機能を思いついたりする。そんなときにさっと作れるのが素晴らしい。しかも、データはすべてクラウドにあるので、一度環境を作ってしまえば、PCもOSも選ばない。Windowsデスクトップでコード書いてて急に出かけても、Ubuntuノートで続きが書ける。僕のような引篭りにはあまり関係ないが、よく出かける人は便利だと思う。

かといってけっこう凝ったこともできて、例えばFusion tablesというGoogleが提供するデータベースサービスにクエリを投げて、クラウドなデータベースを作れる。上手く使えばサーバーにモバイルのセンサ情報を送って処理したりできる。ぽい。

というわけで、プログラムかじったことある人は使ってみると良いと思います。
App Inventorと関係ないけど、VirtualBoxにx86用Androidをインストールして、ホストオンリーアダプタ経由でデバッグすると、糞重いAndroidエミュレータとオサラバできてより快適です。このデバッグ方法もおすすめ。

XtionによるSkeleton Trackingの弱点

Xtionによる、というかOpenNIによるのかな?
ライブでの利用を想定して、プロジェクタ画面との位置関係の算出をしようとゴニョゴニョしていたけど、どうもうまくいかない。
結論から言うと、骨格認識の精度が悪い。KinectとかXtionとかは、Motion detectするために、Realtime性重視のアルゴリズムになっているらしく、Frame rateは速いが、その分精度はよくないらしい。
特に後ろ姿の認識や、壁の近くでの認識率が非常に良くない。手や頭の座標精度というよりは、手や頭が在るかどうかの認識が出来なかったり、柱を誤認識したりする。
まあ、もともとゲームなどの用途だし、しょうがないか。。3D点群の座標自体の精度は思ったよりよさそうなのに、残念。
横向きに撮るなどして精度改善を狙おう。

Kinect互換デバイスXtion Proで遊んでる

Xtionで色々遊んでいます。
とりあえず、ジェスチャー認識で色々やってみてたりする人がたくさん居る中で、新しくて使えそうなことをやりたかったので、ちょっと数学を使う分野に手を出してみている。
やりたい事は、プロジェクターとのカップリング。プロジェクターで映像が映せるとこに持って行って、適当に設置して、ちょっとキャリブレーションするだけでスクリーンの位置を認識して、なんかスクリーンの前に立つ人とのインタラクションする。
Xtionでとった3次元空間から平面っぽいところを認識して、人がプロジェクターの映像の四隅を指さしたりすることで、プロジェクター画面の座標と3次元座標を対応付ける予定。

いつか書いた開発環境についてはVisual Studio on WindowsとMonoDevelop on Linuxを横断して、Dropboxでプロジェクトファイルごと同期しながら書いてる。特に安物ノートPCのUbuntu上でこれほど簡単に空間認識できるのはヤバい。
後はMacの動作確認をしたい所。

Gtk#でWorker threadからのGUI更新のInvokeがうまくいかない

最近悩まされたBugのメモ。

最近メインで使うのがLinuxなので、Cross-platformなGUI ToolkitとしてGtk#を使っている。MonoDevelopにGUIデザイナが統合されていて、Linuxでコード書くときには非常に便利。
ところが、最近悩まされていたメモリリークの原因がどうやらGUI周りだったようで、僕の勉強不足なのか、ToolkitのBugなのかはよくわからん。内容はよくあるWorker threadからの定期的なGUI更新。Windows FormsでいうところのBeginInvokeする場面。プログレスバー表示とかの時のアレね。
Gtk#の場合にどうやってやるかというと、Mono Projectのサイト内に書いてある通りにGtk.Application.Invokeしたり、Gtk.ThreadNotify使ったりすればよい。はずだった。。

気づいた過程としては、なぜかGC.Collect()してるのにメモリ使用量がどんどん増えていて、CLR Profilerで見てみるとManagedメモリは正常。パフォーマンスモニタでUnmanagedなメモリがリークしてる。Unmanagedな処理は極力避けてるぞ?と思って思い当たったのがGtk#でした。

しかしこれからGUI Toolkitどうしよう。Cross-platformでC#から呼べるのってQtとかが思いつくけど、QtのC#ラッパーがUbuntu11.10のリポジトリには見つからないぞ?

今回、CLR Profilerとかパフォーマンスモニタとかで、メモリの中身を調査する方法がかなり理解できたので、まあ勉強にはなった。

.NET FrameworkでLOH断片化によるメモリリークもどき

ちょっと前に、画像とかをManagedな配列で持つと、処理は遅いけどGarbage Collectionしてくれるし良いかも的な事を書いたけど、どうやら遅いだけでは無いらしい。

Garbage Collectionがメモリの配置をゴニョゴニョ弄ってくれるおかげでメモリリークをある程度気にしなくて良いかと思いきや、やはり巨大なデータをゴニョゴニョするのは時間がかかるらしく、C#(というかCLR)では85kbよりでかい配列などのメモリはLarge Object Heap (LOH)に入れて、再配置はしないようになってるそうです。
http://msdn.microsoft.com/ja-jp/magazine/cc534993.aspx

てことで、画像とかGC任せで管理するのは危険とおもはれる。
アプリを開いてから閉じるまでの枚数が限られてたりする場合はいいけど、そうじゃない場合は断片化してメモリ食っちゃう可能性がありそう。
まあ考えてみれば当然ですよね。世の中の画処理ライブラリもそうなってるし。。
でも僕のような素人のために画処理の本の最初に書いといて欲しい。

結局Marshal使ってunmanageで頑張るしか無いらしい。
msec単位で時間かかるとしても、GCにLOHメモリの再配置を指示できればいいのに。。。

C#でポインタとbyte配列の高速なやり取り

C#で、ポインタとバイト配列を相互にやり取りしたい事が多い。
例えば、画像の画素値を高速に得るためにBitmapData.Scan0を使いたいけど、byte[]に入れて色々処理したい時とか。
Marshal.Copyでいいじゃんと言われそうだけど、たとえばRGB画像のR画像だけ欲しい時、いちいち全部Marshal.Copyしてから扱うのは無駄に思える。
(実際は中の人がDMAを使ってるのか、すごく速い)

やり方は色々思いつくけど、どれが高効率かわからないので、実験してみた。
以下Marshalクラスを眺めたりして思いついた方法。IntPtrが指すRGB画像を色ごとにbyte[]にぶち込むのが目標とする。

  • managed
  • Marshal.Readbyte(…)を使う
  • Readbyte(ptr, ofs)でofsをインクリメント
  • アドレスをインクリメントして、Readbyte(new IntPtr(addr))する
  • Marshal.Copyで普通にやる
    • 全画像Copyして、配列で頑張る
    • 全画像Copyして、1色ずつ画像を完成させていく(Read画像とWrite画像が1つずつにできるので、キャッシュを期待)
    • Line毎にCopyしてみる
    • 画像を幾つかのパートに分けて、マルチスレッド化してLine毎にCopyしてみる
  • unmanaged
    • ptr.ToPointer()からfixed(byte* R_Image)にポインタインクリメントしながらコピー
    • ptr.ToPointer()からMarshal.AllockでコピーしてからMarshal.Copy
    • unmanagedmemorystreamからReadByteする

    結論から言うと、Marshal.ReadByteやUnmanagedMemoryStreamは遅かった。前述した通り、Marshal.Copyはとても速いので、これらの関数はこの用途には使えないね。ググってもほとんどMarshal.Copyしか出てこないのはこういう訳か。
    unsafeポインタ系はやっぱり速いけど、unsafeはあんまり使いたくないので、Line毎にMarshal.Copyして弄るっていう処理を複数スレッドでやることにする。

    以下、検証に使った関数たち
    続きを読む

    C#でGenericなJag配列の生成と多次元配列からの変換

    以前に、C#で配列の初期値つきの初期化について書きましたが、今回は更に多次元配列とかJag配列とかを簡単に作りたいっていう話。

    C#では多次元配列(a[2,3]みたいなやつ)も使えますが、僕はJag配列(a[2][3]みたいなやつ)の方が圧倒的に使用頻度が高いです。配列の配列っていう概念の方がわかりやすいし。
    できることとしては何が違うか知りませんが、引数の都合などでたまに多次元配列をJag配列化したいことがあります。
    最初は任意の次元の配列も再帰とかで書ける気がしたんだけど、実は書けないっぽい。

    ついでに、以前の記事のように初期値つきJag配列初期化についても考えたけど、こちらも再帰的に書けないきがしている。
    多次元の配列の初期化は、次元が増えるほど面倒なので、とりあえず妥協して、途中の次元まではArray型の配列型、最後の配列だけGenericに生成するようにして、初期化付きJag配列生成メソッドを書いてみた。

    public class k2kArray
    {
        public static T[][] ConvertToJag<T>(T[,] array)
        {
            int i, j;
            var ret = new T[array.GetLength(0)][];
            int l = array.GetLength(1);
     
            for (i = 0; i < ret.Length; ++i)
            {
                ret[i] = new T[l];
                for (j = 0; j < l; ++j) ret[i][j] = array[i, j];
            }
     
            return ret;
        }
     
        public static TElem[] Init<TElem>(TElem[] arr, TElem InitialValue) where TElem : struct { return Init<TElem>(arr, () => InitialValue); }
        public static TElem[] Init<TElem>(TElem[] arr, Func<TElem> InitElem) { return Init<TElem>(arr, (i) => InitElem()); }
        public static TElem[] Init<TElem>(TElem[] arr, Func<int, TElem> InitElem)
        {
            int i;
            for (i = 0; i < arr.Length; ++i) arr[i] = InitElem(i);
            return arr;
        }
     
        public static TElem[] CreateInit<TElem>(int Length, TElem InitialValue) where TElem : struct { return CreateInit<TElem>(Length, () => InitialValue); }
        public static TElem[] CreateInit<TElem>(int Length, Func<TElem> InitElem) { return CreateInit<TElem>(Length, (i) => InitElem()); }
        public static TElem[] CreateInit<TElem>(int Length, Func<int, TElem> InitElem) { return Init<TElem>(new TElem[Length], InitElem); }
     
        public static Array CreateJagArray<TElem>(Func<TElem> InitElem, params int[] Length)
        {
            return CreateJagArrayDelegate<TElem>(Length, Length.Length, InitElem)();
        }
     
        public static Func<Array> CreateJagArrayDelegate<TElem>(int[] Length, int Dimension, Func<TElem> InitElem)
        {
            if (Dimension == 0)
            {
                return () => CreateInit<TElem>(Length[Dimension], InitElem);
            }
            else
            {
                return () =>
                          CreateInit<Array>(Length[Dimension-1],
                                CreateJagArrayDelegate<TElem>(Length, Dimension - 1, InitElem)
                          );
            }
        }
     
    }

    なんか微妙。string[][]の初期化とかしたいんだけど、Array[]になっちゃう。。
    その後キャストするにしてもうまい方法が思いつかない。
    なんかいい方法ないかな。っていういつもの結論。

    グラフ描画

    学生時代は特に、.NET Framework上で作ってるソフトでちょっとしたグラフを表示したい事がたまにあった。Office Web Componentsとかを使ったり、他のグラフ描画ソフトやExcelで楽なようなCSVを吐いて誤魔化したりしていたけど、どうも巧い方法が無かった。
    最近はもう自分である程度のものは作って持っとこうかと思い始めていたけど、久しぶりに調べてみると、なんかMicrosoftがコントロール作ってた!

    チャート・コントロールを使うには? − @IT

    まだドキュメント少ないけど、プロパティ名見ればいろいろわかるし、OWCでできていた事はたいていできそう。機能を端折って描画を速くした散布図(FastPoints)とかあるっぽい。

    3軸の3D散布図とか、ベクトルが描けるといいんだけどなー。まだいじってないからわからん。
    あとWPFで同じような機能欲しいな。。探せば有るかな。。なさそうだな。。
    この辺必要な人種はMicrosoftのFrameworkなんか使わないんだろうね、きっと。

    複数のRSSを統合

    ずーっと前に、いろんなサイトのRSSをマージして1つのRSSにして配信するサービスを探して、うまく見つけられなかった覚えがあるんだけど、Google Readerで出来ることに気付いた。
    Twitterも、はてブトップ記事も、友人の日記もまとめてモバイルのRSSリーダで読めたりして便利。
    Google Readerはフィードの無いページのRSSを自動生成する機能も付きそうだし、これは使えるかも。

    フィード統合したRSSの見かた

    1. Google Readerでフォルダを作成し、フィードをぶち込む
    2. フォルダをクリック
    3. 画面右上らへんにある”詳細を表示”をクリック
    4. RSSのURLが表示されます。
    1 2

    ホーム > Tips

    カレンダー
    « 2018 年 1月 »
    S M T W T F S
      1 2 3 4 5 6
    7 8 9 10 11 12 13
    14 15 16 17 18 19 20
    21 22 23 24 25 26 27
    28 29 30 31      
    最近の反応
    メタ情報

    ページの上部に戻る