Windows 10 が動作する Raspberry Pi 2 Model B の考察

Raspberry Pi 2 Model B発売。4コア化&1GB RAMでWindows 10も対応、6倍高速 – Engadget Japanese
http://japanese.engadget.com/2015/02/02/raspberry-pi-2-model-b-4-and1gb-ram-windows-10-6/
マイクロソフト、Raspberry Pi 2 にWindows 10 を含む開発環境を無償提供 – Engadget Japanese
http://japanese.engadget.com/2015/02/02/raspberry-pi-2-windows-10/
Raspberry Pi 2 runs free Windows 10, costs $35 – CNET
http://www.cnet.com/uk/news/raspberry-pi-2-model-b-is-a-quad-core-upgrade-on-sale-today/

2個注文したので、ざっと備忘録的に書いておきます。ちょうど、先日 MVP Community Camp で 「Raspberry Pi で動かすロボットアーム(meArm)」を発表したばかりなので。

去年の夏ごろに、USBポートが4つある Raspberry Pi Model B+ が発表になって、どーしたものかなと思っていたのですが、ここに来て、RAspberry Pi 2 の発売です。値段的には数百円しか変わらないので上位バージョンとして買っておく訳ですが(手元にあるのが、初代の256MB の RasPi なので)、実は Windows 10 を動かすにはクリアされなければいけない(Microsoft がクリアする訳ですが、しかも6か月間のうちに)難関がいくつかあります。

ちなみに、以前のバージョンに Windows 10 は載るのか?というと載らないみたいですね。今回の RasPi 2 では SoC(System on a chip)を搭載したことで、Windows 10 なり Ubuntu なりが動くことができるとのこと。

CPU が ARM

Intel 系の CPU ならば、そのまま載せればいいのですが、RasPi 2 の CPU は ARMv7 です。つまりは、Surface RT と同じように ARM 系なわけです。Surface RT 2 が生産中止で、ARM と WinRT の組み合わせが下降線になっている(?)ときに、再び、ARM 系に合わせないといけないわけですね。Visual Studio 自体には ARM コンパイラが入っているので、それでコンパイルしてインストール。ただし、Surface RT では、ARM 実行ファイルはそのまま入れられなかったので、その制限は緩くしなければいけないわけです。とはいえ、実行許可のガードだけかかっているので、それを外すだけでいけるのか、それとも、Windows の ARM 版がそのまま移行できるかどうかは不明なところです。

GPIO を直接アクセスする

Windows 8 あたりだったか、OS から GPIO の直接アクセスがかなり制限されています。WinRTからは絶望的(?)なので、デスクトップアプリからアクセスすることになるのですが、この手のアクセスはカーネルか特権で動かさないとだめですよね。実際、Linux からは sudo 等で特権で動かないとポートアクセスができません。ここには特定のドライバーを入れるのか、デスクトップアプリ自体を特権(管理者権限)で動かすのか、ってところです。まあ、RasPi の Windows 10 を入れてマルチユーザーで動かすことは少ないでしょうから、管理者権限のユーザーを作っておけばいいだけかもしれませんが。RasPi の場合は、USB アクセスじゃなくて、GPIO アクセスができて I2O コントローラーで制御できるってのが有利な点なので、ここは外せないところです。

.NET Compact Framework になる?

ここは予想なのですが、SD メモリ内で動く Windows Embedded 的な機能とポートアクセスな機能が必要なわけで、.NET Compact Framework が搭載される感じになるのかなと思っています。

MVP Global Summit 2014 感想戦 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6603

の中でも書きましたが、

Microsoft’s fitness band: What kinds of software and services are inside? | ZDNet
http://www.zdnet.com/article/microsofts-fitness-band-what-kinds-of-software-and-services-are-inside/

にある、Windows 10 “Athens” のところには、Windows Embedded Compact があって、ここには .NET Compact Framework が載る予定なんですよね。勿論、RasPi 2 に Windows Mobile のところを割り当てるパターンも考えられるのですが、Mobile のほうだとセンサーの制御とかがしづらくと、そうなるとせっかく RasPi 2 に乗っているモジュールが全滅ってことになりかねない。ここは、ぜひ GPIO を手軽に扱える環境を提供してほしいところです。まあ、.NET CF ってことになると、それはそれで制限が多いわけですが、デスクトップアプリを動かすことは少ないだろうし(HDMIはついているけど、それを使ってタッチパネル/ストアアプリを動かすことは少ないかなと)。まあ、ディスプレイが無い=無償提供ってことで、Windows Mobile のほうを提供するパターンもあるのですが、その場合はセンサーの類を頑張って貰わないと。

とはいえ、インテルのミニPCよりも断然安いし、USB給電なので電気維持費もかからないので、常時接続のモデルを作るのは都合がいいボードですよね。私の場合は、

  • ディスプレイ無し(デスクトップなし・ストアアプリなし)
  • Telnet 系の接続が必須
  • GPIO, I2C, カメラモジュールの接続が可能
  • BrickPi のような拡張ボードの接続が可能
  • USB ドングルの WiFi あるいは Bluetooth 接続

が必須なわけです。Linux で Bluetooth(ゲームコントローラー)接続がちょっと面倒なので、そのあたり Windows 10 を載せると改善されたら手軽にできてよいかなと。

カテゴリー: RaspberryPi | Windows 10 が動作する Raspberry Pi 2 Model B の考察 はコメントを受け付けていません

Xamarin Android Player をきれいに削除する方法

Xamarin Android Player でデバイスを削除しようとしても、なかなか削除できないことがあります。普通は「Delete」で削除して、再ダウンロードすればいいんですが、間違って Oracle VM VirtualBox で仮想ドライブを削除すると、かなり嵌ります。

image

なぜか、Xamarin Android Player をアンインストールしても壊れた Installed Devices が復活するし、これはどうしたものだろう…と思っていたのですが、対処方法がありました。

Cannot delete Xamarin Android Player Virtual Devices – Xamarin Forums
http://forums.xamarin.com/discussion/30620/cannot-delete-xamarin-android-player-virtual-devices

上記では、installeddevices.json を修正する方法も書かれていますが、きれいさっぱりと設定を消すだけならば、C:ProgramDataXamarinAndroidPlayer フォルダを消してしまえば ok です。そして、再び Xamarin Android Player をインストールすれば、最初の状態(デバイスがインストールされていない状態)になります。

image

これで暫くぶりに Xamarin Android Player が正常に動くようになります。

こんな風に、Xamarin.Android を HTTPサーバーにしてコマンド受付と画像転送がしたかったんですよね。System.Net.HttpListener を使うのですが、Android Emulator のほうは IP アクセスができない(10.0.2.15 などが通らない)ので、実機を使うか、Xamarin Android Player を使えるか?って感じだったのです。こっちは、10.71.34.102 が割り振られていて、ホストしている PC からアクセスができます。

image

ちなみに、こんな風に Android TV アプリとして完成させる予定です。

image

image

カテゴリー: Xamarin | Xamarin Android Player をきれいに削除する方法 はコメントを受け付けていません

Rolling Spider を買って SDK で遊ぼう(出帆準備編)

娘のサンタクロースに Rolling Spider を貰ったので、ちょっと遊び&調べてみました。

http://www.parrot.com/static/images/theme/catalog/rolling_spider/details.jpg

Jumping Sumo のほうは、夏あたりに見たのを覚えていたのですが、こっちのほうもワンセットで発表されていたのです。実は、先日の MS グロサミで MVP の方がコントローラを使ってデモをやっていて、中身で何が動いているのか知りたかったのです。その後に行った MS ストアに売っていて Surface でデモをやっていたので、.NET Micro なのかと思っていたのですが、組み込み Linux だそうです。操作は、Bluetooth v4 が装備されている iOS/Android/Windows Phone があれば ok です。FreeFlight 3 のストアアプリ版もあるので、初代 Surface RT を使って動かすこともできました。ただし、Surface の場合は、Bluetooth のペアリングなかなかつながらなくて、手元の iPod のほうがスムースにつながります。

Parrot、ミニドローンRolling SpiderとJumping Sumoを国内向けに解説。SDKも公開 – Engadget Japanese
http://japanese.engadget.com/2014/07/10/parrot-rolling-spider-jumping-sumo/
パロット社のミニドローンRolling Spiderは、地上から天井まで自在に駆け巡ります!
http://www.parrot.com/jp/products/rolling-spider/
Windows ストア の Windows 用 FreeFlight 3 アプリ
http://apps.microsoft.com/windows/ja-jp/app/freeflight-3/3c827d26-a7fa-430e-9a1f-bb33670d0551

Rooling Spider 自体は、二年前に発売された AR Drone のおもちゃ版?みたいなものです。AR Drone 自体は 4万円ほどするのですが、Rooling Spider は1万円ちょっとです(私の場合、ちょっと安い時期を見つけて1万円弱で買えました…いや、サンタ的に)。たぶん、カメラが付いてないだけで、中身は一緒のものではないかなと。カメラを積む分だけ AR Drone は非常に大きいのですが、Rooling Spider は部屋で飛ばせるぐらい小さなものです。部屋用のミニヘリコプターと同じですね。

ただし、普通のラジコンと異なるのが Bluetooth で操作できる(操作しなくてはいけない)ところです。Bluetooth だと、タイムラグが必ず出る(0.1~0.2秒ぐらい遅れる)ので操作的にはどうなんだろう?と思っていたのですが、大丈夫みたいです。Parrot 社は、オーディオ機器を作っているメーカーでそのあたりのノウハウが入っているようです。

中身は組み込み Linux

Bluetooth 制御やモーター制御等をしているのは組み込み Linux です。オープンソース化されているので、機器を作れる…んですよね。手元にある CloudFlash も組み込み Linux で busybox なんかが使われているのでわかります。

OpenSource-RollingSpider – 概要 – Parrot ASTEROID Developers Zone
https://devzone.parrot.com/projects/show/oss-rolling-spider

ファームウェアアップデートは、FreeFlight アプリからか、PC から USB ケーブル経由で行えます。私の買った時点で、既にファームウェアが古くなっていたので、最初に行うのがファームウェアアップデートでした。出荷時点とアプリの日にちのずれがあるので、これは仕方がないところです…が素人にはちょっと辛いかも。アプリの Bluetooth 経由から行うと非常に時間がかかります。アップデート開始自体はアプリに組み込まれているので、難なく進むのですが、なかなか終わらないかつ最後になって失敗するという状態で。USB ケーブル経由のほうが良いかもしれません。

Rolling Spider の組み込み Linux 自体は手がでません(と思う)。SD カードとかついてないし。しかし、Bluetooth 接続する操作アプリのほうに手を出すことができます。というか、そういう仕様になっている。

アプリは ARDroneSDK3 を使う

発表では SDK を使えるようにする、となっていたもののリンクがありませんでした。Parrot 社からのリンクも見当たらないので、探すのが苦労したのですが、github 上にありました。

ARDroneSDK3
https://github.com/ARDroneSDK3
ARDroneSDK3/Samples
https://github.com/ARDroneSDK3/Samples

「MiniDroneDeviceController is used to control the RollingSpider」とあるので、Rooling Spider も動かせそうです。中身はざっとしかみていませんが、C# 版はありません。が、ストアアプリ版があるので、動作は問題ないと思われます。

iOS 版で動かしてみて、Xamarin でくるむ?

iOS 版の MiniDroneDeviceController を Xamarin でラップしてやれば、普通に C# から使えるようになるかな、と。おそらく Bluetooth 接続するための ARNetworkAL とコマンド送受信するための ARCommands が肝になるかな。ARNetworkAL 自体は、WiFi にも対応しているようです。

[AR.Drone]Droneをc#で飛ばしてみようじゃないか (1) » はにらぼ☆てっく
https://www.honeycomb-lab.co.jp/blog/tech/?p=282

な感じで、AR Drone を C# で操作している方も。

カテゴリー: 開発 | Rolling Spider を買って SDK で遊ぼう(出帆準備編) はコメントを受け付けていません

Xamarin と AllJoyn の将来を考える

Xamarin Advent Calendar 2014 の 22日目の記事です。

Xamarin Advent Calendar 2014 – Qiita
http://qiita.com/advent-calendar/2014/xamarin

もともとの予定は、Xamarin.iOS/Android に AllJoyn を乗せてみて通信させてみようかな、と思っていたのですが、ちょっと時間が取れなかったので入り口の部分だけ紹介します。私自身 AllJoyn に詳しいわけではないけれど、今後は詳しくありたいな(つーか、やらんとあかんやろう自分)ってことで書き進めます。

そもそも AllJoyn とは何か?

端的に言えば、デバイス同士を相互通信させる規格です。デバイスとは行っても、ゲームデバイスからデスクトップPCや、ルータや家電なども対象になります。ともかく、ネットワークにつながっているものが対象ですね。

Open Source IoT to advance the Internet of Everything – AllSeen Alliance
https://allseenalliance.org/

クアルコムが主導になって、各種ソースはオープンソースで配布されています。実は AllJoyn モジュール自体は Windows 7 の頃から対応になっていて、夏ごろに Microsoft が AllSeen Alliance に加入しています。

MS、IoTを推進するAllSeen Allianceに加入–クアルコムが主導 – CNET Japan
http://japan.cnet.com/news/business/35050321/

メンバーには、Panasonic、Sharp、Sony、他にも Cisco なども入っているので、ネットワーク機器を問わずということがわかります。

ネットワーク機器(電力線通信や赤外線通信、短距離通信も含む)で機器同士がデータのやり取りをするときに何の規格に則ってデータ通信をするか、ってのが問題です。古い?ところでいえば、ルータなどの機器を MIB で動作チェックしたり、簡易的な WEB サーバーを乗せて本体のデバイスを操作したりします。他にもコンソール接続してコマンド送信ってのもあれば、独自のスイッチングってのもあります。これらは、機器のメモリの問題もあり、内部で動くコード(大抵の場合は C、最近は組み込み Linux でスクリプトを動かすってのもある)の制限もあり、ばらばらでも仕方がないところなのですが、今後、LAN だけでなく、WiFi、Bee なども含めると通信形式自体も多様になれば、機器自体も多様になる(携帯ゲーム端末、冷蔵庫、オーディオ機器、インターネット対応テレビなども含めて)わけで、何かが何かを制御するときに、どう対応すればよいか?ってのは大変なのは目に見えてきています。

そこで、それらのプロトコルを XML 形式といくつかのコマンド(GET/SET)に絞って使うように統一してしまおうというのが AllJoyn の目的です。勿論、通信形式だけでなくて、Push/Pull を実現するためにネットワーク的に Hub があったりする訳ですが、そのあたりは多機能化≒肥大化とシンプルさ≒単機能で貧弱、とのせめぎあいです。ある意味で、Raspberry Pi でよく使われる webiopi に似ています。AllJoyn のほうはデータ自体が XML で流れるのでおそらく HTTP プロトコルが使われるのでしょうが、個々の機器に Web api を作ってサービスを定義するよりは、ある程度コマンドが決めてあって内部データの形式(必須データと推奨データなど)が決まっているほうが、今後の拡張がしやすいでしょう(実際、かつての MIB はそんな形で拡張されてきています)。

AllJoyn はオープンソースである

各種の機器に広くインストールされないといけないので、オープンソースになっています。対応する OS も Android, iOS, Windows そして当然 Lunux もあります。そもそも、ソースの管理自体は、前年ごろから Linux foundation に移管されて、オープンソースとしての権利関係の地盤固めをしているようです(おそらく、クアルコムも含めて将来的に特定の企業が権利を主張しないように、という縛りだと思います)。

Download – AllSeen Alliance
https://allseenalliance.org/developers/download

バージョンが ver14 になっていますが、すごく完成されている訳ではなくて、Firefox のようがんがんバージョンを上げているだけでしょう。

image

ソースをダウンロードして展開すると、java や javascript のコードもあります。ちなみに、WinRT からは C モジュールを使うようになるそうです。Core のコードは、OS 自体に組み込まれるそうで、Window 10 からは AllJoyn のモジュールが入ることが決まっています。

ちなみに Xamarin は AllJoyn に対応していないのですが、Android/iOS のモジュールがあるので、それを使えば ok とのことです。

Does AllJoyn work with Xamarin? – Allseen Q&A Forum
https://ask.allseenalliance.org/question/677/does-alljoyn-work-with-xamarin/

AllJoyn で何ができるのか?

具体的に何ができるのか?ってのは、下記の showcase から見ていくとわかりますが、今よく使われているのは、ゲームアプリの相互通信や、スマートフォンからテレビやオーディオ機器を操作するアプリです。

Showcase of Products using AllJoyn – AllSeen Alliance
https://allseenalliance.org/showcase

スマートフォンからテレビを操作する、という方法自体は決して新しいものではありません。赤外線通信をエミュレートしても良いし、適当なリモコンアプリをテレビとスマートフォンの相互に入れれば操作ができるようになるでしょう。ただし、それらのアプリは専用のアプリになります。もちろん、これらの通信をオープンで公開すればいいのでしょうが、それを呼び出すプロトコルはいちいち異なる可能性が高くなります。それは、公開されている WEB サービスのように独自な形式になるでしょう。

そこで、相互に接続する機器を一旦切り離します。テレビ側のアプリは受信アプリとして独立して、スマートフォンのアプリは操作するアプリとして独立させます。その間のプロトコルは、ごく単純な XML 形式で流して、それぞれで解釈をします。実は、この XML 形式なり公開されたプロトコルなりが一般に認知されれば、AllJoyn である必要はありません。と同時に、この通信するプロトコルが AllJoyn が定義するプロトコルというだけです。End-to-End だけ見れば、それぞれに公開された XML 形式のフォーマットは、同時に切り替えが可能というわけで、テレビの受信データ形式が同じであれば、スマートフォンのアプリは何であっても構いません。新しく作ることも可能です。同時に、スマートフォンアプリから送るデータ形式さえあわせておけば、テレビを新調することも可能です。

同じことは、相互通信のゲームアプリにも言えて、基本的なデータ形式だけ同じであれば、別なアプリで拡張することも可能です。ピアツーピアの接続自体は、AllJoyn のネットワークが賄ってくれる(ハズ)なので、そのあたりの手間も省けます…と、どこまでできるか分かりませんが(データ量的に、バイナリ通信を併用しないと無理、っていうパターンもあるでしょうし)、いくつかそういう試みがされています。実際、先のサンプルコードに Unity が入っているので、そのあたりも範疇にはいっています。

で、Xamarin と AllJoyn はどうなのか?

現在のところ、Xamarin.iOS/Android からネイティブの AllJoyn ライブラリを使う方法は用意されていませんが、iOS/Android モジュール自体があるので、そのうち使えるようになるでしょう(どちらが対応するかわかりませんが、オープンソースなのだから自分でバインドしてもよいし)。そこで、使えることを前提にして考えると、Xamarin の使いどころとしては、

  • スマートフォン/タブレットの相互通信に使う
  • スマートフォンから、AllJoyn 対応の機器を操作するために使う

の2種類ですね。スマートフォン同士は、ゲームアプリとかチャットアプリを作って試すことができるでしょう(ハブは必要なのかな?)。Azure の Mobile Service を使う方法もあるけど、まあ、お試しとして。もちろん、普通の PC からも操作できるはずです。

別の機器を操作するものとして、AllJoyn 対応の機器を用意する…ことはできないので(販売されているものはあるのかな?)、Raspberry Pi を使うと良いかも、と思っています。C 言語ベースなので、Arduiono か netduiono で動く感じもするんですが、 Using Arduino+Alljoyn to control blinds – YouTube こんなのもあるし。ひとまず、Raspberry Pi に AllJoyn を入れて meArm を操作させたいところです。手元で作っている meArm ライブラリの .NET 版は、 REST で動かしているのですが、これを AllJoyn に対応させればいいですよね。このあたり、スマートフォン/タブレットと、IoT な機器とをつなげるのに、Xamarin+AllJoyn は結構有力かなと思ってます。

カテゴリー: AllJoyn, Xamarin | Xamarin と AllJoyn の将来を考える はコメントを受け付けていません

Let’s call Fortran DLL from F# language.

This text is 14th article in F# Advent Calendar 2014 in Japanese.

The original article’s the Japanese, but since there was a request, I am rewriting in English. So this year is also in English version, and users to access the F# Advent of English version and traced from the following.

F# Advent Calendar 2014 – connpass
http://connpass.com/event/9758/
F# Advent Calendar in English 2014 | Sergey Tihon’s Blog
http://sergeytihon.wordpress.com/2014/11/24/f-advent-calendar-in-english-2014/

Well, last year it wrote of that “before the F# and Fortran story … of” What it is sadly the setback was me…, this time agein !!! We succeeded in calling a Fortran from F#, who deals and technical information for you, but the time being, because the head is harf-joke article capital F connection :P

Make DLL by Fortarn

This DLL is made by Intel Visual Fortran 2013.

Intel Fortan can make DLL on Windows. Export Function is defined “!DEC$ ATTRIBUTES DLLEXPORT::<EXPORT-FUNCTION>”. We have a fortran fo GNU, but without that it was made only static libraries more of over there, I do not know well. However, it is possible to to create a *.so file. If you are run on linux use as it is from the C language, you’ll probably make in a manner similar from F#.

! This function has two number parameters.
integer function add1( a, b )
    !DEC$ ATTRIBUTES DLLEXPORT::ADD1
    integer, intent(in) :: a, b
    integer :: total

    total = a + b
    add1  = total
end function add1

! This function has a One-dimensional array parameter.
integer function sum1( v, count )
    !DEC$ ATTRIBUTES DLLEXPORT::SUM1
    integer, intent(in) :: v(10)
    integer, intent(in) :: count
    integer :: i, total

    total = 0
    do i=1,count
        print *, 'in sum1: ', i, v(i)
        total = total + v(i)
    end do
    sum1 = total
    end function sum1

! This function has a Two-dimensional array parameter.
integer function sum2( v, cnti, cntj )
    !DEC$ ATTRIBUTES DLLEXPORT::SUM2
    integer :: v(3,4)
    integer :: cnti, cntj
    integer :: i,j
    integer :: total

    total = 0
    do j=1,cntj
        do i=1,cnti
            print *,i,j,v(i,j)
            total = total + v(i,j)
        end do
    end do
    sum2 = total
end function sum2

Fortran of contents is too cheap, but I have tried an array numeric (int type). To after practice, We should try double, the per float.

Try to call from C++ Language

Let’s call from C++ in order to confirm the operation. The DLL function that is published from Fortran, and I call using the dllimport, but I just want to note is where we pass the value is in the pointer. because via global variables rather than via this Fortran function of passing stack. In the case of C language and pass laden with value on the stack (C# same when passing from a .NET language, etc.), when it passed to Fortran, that do not attention to this, it’s a strange feeling. Well, when you’re doing just Fortran, and so convenient to be very well done to be taken into account (like pass as it is a huge array).

#include &quot;stdafx.h&quot;
#include <iostream>

#define DllImport __declspec( dllimport )

extern &quot;C&quot; {
	DllImport int ADD1(const int *, const int *);
	DllImport int SUM1( int(*)[] , const int *);
	DllImport int SUM2(int(*)[4][3], const int *, const int *);
}

int _tmain(int argc, _TCHAR* argv [])
{
	int x = 10;
	int y = 20;
	int ans = ADD1(&x, &y);
	std::cout << &quot;ans &quot; << ans << std::endl;

	int  v[] = { 1, 2, 3, 4, 5 };
	int cnt = 5;
	int ans2 = SUM1((int(*)[])&v, &cnt);
	std::cout << &quot;ans2 &quot; << ans2 << std::endl;

	int v2[][3] = {
		{1,2,3},
		{11,22,33},
		{10,20,30},
		{100,200,300}
	};
	int cnti = 3;
	int cntj = 4;
	int ans3 = SUM2( &v2, &cnti, &cntj);
	std::cout << &quot;ans3 &quot; << ans3 << std::endl;

	return 0;
}

If we run this code, you will like that.

Try to Call from C# Language

Let’s rewrite in C#. And to use the DllImport is we ware found, but it does not do not pass a pointer int type, we can use the ‘ref’ keyword. Call form of the function, we need to be defined explicitly “CallingConvention = CallingConvention.Cdecl”.

class Program
{
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int SUM1([In] int[] v, [In] ref int count);
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int SUM2([In] int[,] v, [In] ref int cnti, [In] ref int cntj);
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int ADD1([In] ref int a, [In] ref int b);

	static void Main(string[] args)
	{
		int a = 10;
		int b = 20;
		int ans = ADD1(ref a, ref b);
		Console.WriteLine("ans {0}", ans);

		int[] v = { 1, 2, 3, 4, 5 };
		int cnt = v.Length;
		int ans2 = SUM1(v, ref cnt);
		Console.WriteLine("ans2 {0}", ans2);
		/*
		int[][] v2 = {
							new int[]{1,2,3,4},
							new int[]{11,22,33,44},
							new int[]{10,20,30,40},
						};
		*/
		int[,] v2 = {
						{1,2,3},
						{11,22,33},
						{10,20,30},
						{100,200,300},
					};
		int cnti = 3;
		int cntj = 4;
		int ans3 = SUM2(v2, ref cnti, ref cntj);
		Console.WriteLine("ans3 {0}", ans3);
	}

When you pass a two-dimensional array, int[][] in rather than int[,] you can use the C++ and because the int value the same as in the contiguous memory and Fortran is to be placed. When we call the ADD1 function is cumbersome put the ref to, but you can call this correctly the DLL of Fortran.

Try to call from F# !!!

Let’s rewrite more F#. This pointer which is export from dll is int& we declare as.

open System
open System.Runtime.InteropServices

type ARY2D = int[,]

[<AutoOpen>]
module FDLL =
  [<DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)>]
  extern int ADD1(int& a, int& b)
  [<DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)>]
  extern int SUM1(int[] v, int& count )
  // cannot use int[,], so we defined 'ARY2D' alias class.
  [<DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)>]
  // extern int SUM2(int[,] v, int& cnti, int& cnt2 )
  extern int SUM2(ARY2D v, int& cnti, int& cnt2 )

let mutable a = 10
let mutable b = 20
let ans = ADD1( &a , &b )

Console.WriteLine( &quot;ans {0}&quot;, ans )

let mutable v = [|1;2;3;4;5|]
let mutable cnt = v.Length
let ans2 = SUM1( v, &cnt )

Console.WriteLine( &quot;ans2 {0}&quot;, ans2 )

// two-dimensional array is made by Array2D module.
let vv = [|
    [|1;2;3|];
    [|11;22;33|];
    [|10;20;30|];
    [|100;200;300|];
  |]
let v2 = Array2D.init 4 3 ( fun i j -> vv.[i].[j])

let mutable cnti = 3
let mutable cntj = 4
let ans3 = SUM2( v2, &cnti, &cntj )

Console.WriteLine( &quot;ans3 {0}&quot;, ans3 )

C# is not enough … write simpler compared with F#, I do not change much. Than that, it’s worrisome is is where you must use let ‘mutable’ is to want to pass by const. This is a limitation of Fortran call, in order to pass a pointer value, the variable of a even if it is not changed content is not pass and do not ‘mutable’. Here is where I want to twist. Though it pains of immutable values, it is a place me.

C# 2-dimensional array in int [,] since the was an unclear writing is how I in F # … but, how was I understand. With Array2D int [,] you can make a considerable thing. This, what another twist necessary int when you extern [,] it can not be the type specified in, we will create the alias. Here, extern int SUM2 by creating a type alias that ARY2D and is doing. In this way, you will be passed as the same as a two-dimensional array with C++.

Oh, Order of two-dimensional array will not unlike those of C++, but this is that the charm ;)

At the end

That is why, one New Year’s Eve of projects? As, was able story article dealing with the Fortran from F#. This, or the existing Fortran library can make an app that was made from F#, Who’s the obtained technical information but, Well, it is possible to that wanted to do. Everyone, a good Christmas !!!

カテゴリー: 開発 | Let’s call Fortran DLL from F# language. はコメントを受け付けていません

XAML は Microsoft だけのモノじゃないので、動的にロードできるよという話

XAML Advent Calendar 2014 – Qiita
http://qiita.com/advent-calendar/2014/xaml

XAML アドベントカレンダーの 18 日目の記事です。サーバーから動的に XAML をロードして表示する、というネタを考えていたのですが、と、その前に XAML って何?ってのを書き残しておきます。ちょっと前に Xamarin カンファレンスで Xamarin.formsとカスタムコントロールの話 ってのを話しました。Xamarin.Forms が扱うものが XAML ならば、そもそも XAML とは何か?ってところを突き止めてみます。実は、SPEC があって、MS-XAML(PDF) からダウンロードができます。そうです。XAML の仕様って公開されている情報なのです。なので C# とか ECMAScript のように誰でも実装できる仕様なんですね。誰でも作れるということは、XAML をサポートしているのは WPF や WinStore だけでなく、Xamarin.Forms でもよいし、Linux 上の mono でもよいわけです。名前空間としては System.Xaml が割り当てられていますが、内実は諸々なアセンブリが作られています。WPF が System.Xaml を使っているように WinStore が System.Xaml を使えばよかったのでしょうが、WinRT の関係か使っていません(使えないのかもしれません)。そのあたりは Sliverlight も使っていないので、MS-XAML として仕様は公開され統一されているものの、実装はそれぞれにあるという変な状態になっています…が、「仕様」が決まっているから、その「仕様」にあわせて実装していけば、他のプラットフォーム(あるいはフレームワーク)でも似た感じで使える、という「保証」があります。

で、具体的にどういう点で XAML が XML よりも強化されているかというと(見た目は XML なのだから、XDocument だけで扱うことも可能です)、先の MS-XAML のスペックを見ていくと、

  • x:Class で特定のクラスと結びつける
  • x:Name でクラス内のフィールドと結びつける
  • 名前=”{Binding プロパティ名}” で、指定したプロパティに結び付ける
  • Grid.Row のようなドット付きのタグ名が特別扱いになっている

が規定されていることがわかります。XAML と名乗っている場合は、この仕様が実装されているわけで、逆に XAML を名乗るならば、この仕様を実装しなければいけません。また、XAML を利用する側からみれば、プラットフォームに依存せずに上記の仕組みが利用できるという訳です。つまり、WPF の XAML であっても WinStore の XAML であっても、Silverlight の XAML であっても、Xamarin.Forms の XAML であっても、上記の書き方(クラス、フィールド、プロパティへのバインド)は同じになるということです。これは、特定のクラスへのバインドが XAML 内に書かれているので、適当なアセンブリがロードされれば良いということです。つまり、テキスト形式としての XAML ファイルをそれぞれのプラットフォーム(Windows, iOS, Android, Linux の OS に限らず、あるいは、Java や Objective-C の言語を問わず)に持って行って、適当なアセンブリ(あるいはライブラリ)をロードしてやって、アセンブリ内にあるクラスやプロパティに結び付ける(普通はリフレクションを使う)ことができますよ、って話なのです。

まあ、実際のところは、XAML をデータとして扱っているのは Windows Workflow Foundation ぐらいしかなくて、そのあたりの広がりに関しては失敗しているように見えますが。

更に言えば、名前空間として System.Xaml を用意して、この中に XamlXmlReader クラスがあるのだから、WPF とか WinStore とか Xamarin.Forms とか、このクラスを使って実装すればよかったと思われるのですが、皆ばらばらの実装になっています。おそらく、PCL やら WinRT やらの制約があって、それぞれで XAML をロードする実装が組み込まれたのだと思うのですが…ちょっと SPEC があるのに混乱させ過ぎな感じが。

ちなみに Open Source になった .NET Core には System.Xaml が含まれていません。mono には System.Xaml が入っているので、これをベースにして Linux への拡張をしてもよいかもしれません。

そんなわけで、動的に XAML をロードする方法は

 var url = "http://moonmile.net/up/samplepage.xaml"; 
 var cl = new HttpClient(); 
 var xaml = await cl.GetStringAsync(new Uri(url)); 
 var doc = XamlReader.Load(xaml) as Grid; 
 this.Content = doc; 

な風に簡単に書けます。これは HttpClient でサーバーから XAML データを取ってきている例ですが、ローカルリソースに XAML ファイルを置いてロードさせることも可能です。ただし、XamlReader.Load は、x:Name が使えなかったり、クラスを探索するのが自前のアセンブリのみだったりするので、ちょっと使い勝手が悪いです。逆に、XamlXmlReader を使えばいいんじゃないかと思ったりもするのですが、実は WinRT のほうには System.Xaml がありません。このあたり、完全に View として切り替え可能な XAML と、バインディング先としてのアセンブリ(オブジェクト)は、もう少し煮詰めて考えてもいい気がしています。ちなみに、少々頓挫中の XFormsPreviewer ですが、先の System.Xaml に則ったスタイルに書き直そうかなと思案中です。ドット付きタグ名のあたりが独自処理になってしまっているので、mono の System.Xaml を参考にする感じに。

カテゴリー: XAML | XAML は Microsoft だけのモノじゃないので、動的にロードできるよという話 はコメントを受け付けていません

F# から Fortarn の関数を呼び出そう

この記事は F# Advent Calendar 2014 の 14日目の記事です。今回は英語版もあるそうで、以下から辿っていくと英語版の F# Advent にたどり着けます(当然、中身が英語ですね)。

F# Advent Calendar 2014 – connpass
http://connpass.com/event/9758/
F# Advent Calendar in English 2014 | Sergey Tihon’s Blog
http://sergeytihon.wordpress.com/2014/11/24/f-advent-calendar-in-english-2014/

さて、去年は F#とFortranの話…のその前に というのを書いて、あえなく挫折したワタクシですが、今回は F# から Fortran を呼び出すことに成功致しましたッ!!! って、誰得な技術情報なのですが、いちおう、頭が F つながりというネタ記事なので、お許しを(笑)。

Fortarn で DLL を作成する

DLL は Intel Visual Fortran 2013 を使っています。

Intel の Fortran では、DLL を作成できて、以下のように「!DEC$ ATTRIBUTES DLLEXPORT::<公開名>」のように、DLL で公開する関数を定義できます。gcc にも fortran があるのですが、そっちのほうはスタティックライブラリしか作ったことがなくて、よくわかりません。ただし、linux 上で動かすのならば *.so ファイルを作ってそのまま C 言語から使えるようにできるので、おそらく F# からも似たような形で作れるでしょう。
まあ、Windows 上ならば DLL なので、このスタイルで。

! 数値を渡す簡単なパターン
integer function add1( a, b )
    !DEC$ ATTRIBUTES DLLEXPORT::ADD1
    integer, intent(in) :: a, b
    integer :: total

    total = a + b
    add1  = total
end function add1

! 1次元配列を渡す
integer function sum1( v, count )
    !DEC$ ATTRIBUTES DLLEXPORT::SUM1
    integer, intent(in) :: v(10)
    integer, intent(in) :: count
    integer :: i, total

    total = 0
    do i=1,count
        print *, 'in sum1: ', i, v(i)
        total = total + v(i)
    end do
    sum1 = total
    end function sum1

! 二次元配列を渡す
integer function sum2( v, cnti, cntj )
    !DEC$ ATTRIBUTES DLLEXPORT::SUM2
    integer :: v(3,4)
    integer :: cnti, cntj
    integer :: i,j
    integer :: total

    total = 0
    do j=1,cntj
        do i=1,cnti
            print *,i,j,v(i,j)
            total = total + v(i,j)
        end do
    end do
    sum2 = total
end function sum2

Fortran の中身がチープすぎますが、数値(int型)と配列を試してます。あと実用的にするには、double, float あたりを試しておく必要がありますね。

まずは、試しに C++ から呼び出す

動作確認をするために C++ から呼び出してみましょう。Fortran から公開されれる DLL 関数は、dllimport を使って呼び出せるのですが、値を渡すところがポインタになっているところが注意したいところです。これ Fortran の関数渡しがスタック経由ではなくてグローバル変数経由だからなんですよね。C 言語の場合スタックに値を積んで渡します(C#などの.NET言語から渡すときも同じ)が、Fortran に渡すときは、これに注意しないといけないという、変な感じなのです。まあ、Fortran だけでやっているときは、あんまり考慮しなくてよくて便利(でかい配列をそのまま渡すとか)なので、良し悪しということで。

#include &quot;stdafx.h&quot;
#include <iostream>

#define DllImport __declspec( dllimport )

extern &quot;C&quot; {
	DllImport int ADD1(const int *, const int *);
	DllImport int SUM1( int(*)[] , const int *);
	DllImport int SUM2(int(*)[4][3], const int *, const int *);
}

int _tmain(int argc, _TCHAR* argv [])
{
	int x = 10;
	int y = 20;
	int ans = ADD1(&x, &y);
	std::cout << &quot;ans &quot; << ans << std::endl;

	int  v[] = { 1, 2, 3, 4, 5 };
	int cnt = 5;
	int ans2 = SUM1((int(*)[])&v, &cnt);
	std::cout << &quot;ans2 &quot; << ans2 << std::endl;

	int v2[][3] = {
		{1,2,3},
		{11,22,33},
		{10,20,30},
		{100,200,300}
	};
	int cnti = 3;
	int cntj = 4;
	int ans3 = SUM2( &v2, &cnti, &cntj);
	std::cout << &quot;ans3 &quot; << ans3 << std::endl;

	return 0;
}

実行すると、こんな感じになります。

C# から呼び出してみる

これを C# で書き直してみましょう。DllImport を使うのは分かったのですが、int のポインタを渡さないといけないので、ref を使います。関数の呼び出し形式は、明示的に CallingConvention = CallingConvention.Cdecl を定義する必要があります。

class Program
{
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int SUM1([In] int[] v, [In] ref int count);
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int SUM2([In] int[,] v, [In] ref int cnti, [In] ref int cntj);
	[DllImport("FModule.dll", CallingConvention = CallingConvention.Cdecl)]
	extern static int ADD1([In] ref int a, [In] ref int b);

	static void Main(string[] args)
	{
		int a = 10;
		int b = 20;
		int ans = ADD1(ref a, ref b);
		Console.WriteLine("ans {0}", ans);

		int[] v = { 1, 2, 3, 4, 5 };
		int cnt = v.Length;
		int ans2 = SUM1(v, ref cnt);
		Console.WriteLine("ans2 {0}", ans2);
		/*
		int[][] v2 = {
							new int[]{1,2,3,4},
							new int[]{11,22,33,44},
							new int[]{10,20,30,40},
						};
		*/
		int[,] v2 = {
						{1,2,3},
						{11,22,33},
						{10,20,30},
						{100,200,300},
					};
		int cnti = 3;
		int cntj = 4;
		int ans3 = SUM2(v2, ref cnti, ref cntj);
		Console.WriteLine("ans3 {0}", ans3);
	}

2次元配列を渡すときは、int[][] ではなくて int[,] を使います C++ や Fortran と同じように連続したメモリに int 値が配置されるようにするためです。ADD1 関数を呼び出すときに ref を付けるのが面倒なのですが、これで Fortran の DLL を正しく呼び出せます。

F# から呼び出してみる

更に F# に書き換えてみましょう。dll から export されているポインタは int& のように宣言します。

open System
open System.Runtime.InteropServices

type ARY2D = int[,]

[<AutoOpen>]
module FDLL =
  [<DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)>]
  extern int ADD1(int& a, int& b)
  [<DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)>]
  extern int SUM1(int[] v, int& count )
  // int[,] がそのままでは渡せないので alias を作って指定する
  [<DllImport(&quot;FModule.dll&quot;, CallingConvention = CallingConvention.Cdecl)>]
  // extern int SUM2(int[,] v, int& cnti, int& cnt2 )
  extern int SUM2(ARY2D v, int& cnti, int& cnt2 )

let mutable a = 10
let mutable b = 20
let ans = ADD1( &a , &b )

Console.WriteLine( &quot;ans {0}&quot;, ans )

let mutable v = [|1;2;3;4;5|]
let mutable cnt = v.Length
let ans2 = SUM1( v, &cnt )

Console.WriteLine( &quot;ans2 {0}&quot;, ans2 )

// 二次元配列は Array2D で作る
let vv = [|
    [|1;2;3|];
    [|11;22;33|];
    [|10;20;30|];
    [|100;200;300|];
  |]
let v2 = Array2D.init 4 3 ( fun i j -> vv.[i].[j])

let mutable cnti = 3
let mutable cntj = 4
let ans3 = SUM2( v2, &cnti, &cntj )

Console.WriteLine( &quot;ans3 {0}&quot;, ans3 )

C# と比べて簡素に書ける…ほどではなくて、あまり変わりませんね。それよりも、気になるのは const で渡したいのに let mutable を使わないといけないところです。これは Fortran の呼び出しの制約で、値のポインタを渡すために、内容が変更されなくても a の変数は mutable にしないと渡せないのです。ここはひと工夫したいところです。せっかくの immutable な値なのに、ってところです。
あと、C# での2次元配列 int[,] を F# でどうやって書くのか不明だったので…すが、方法が解りました。Array2D を使うと int[,] 相当なものが作れます。これで、もう一工夫必要なのは extern するときに int[,] で型指定ができないので、alias を作ります。ここでは、ARY2D という型 alias を作って extern int SUM2( ARY2D v, … ) としています。こうすると、C++ と同じように2次元配列として渡せるようになります。

実行した結果は 2次元配列の向きが C++ と逆になっていますが、まあ、こっちのほうが分かりやすいかなと。Xij のほうが X[j,i] よりも書きやすいかなと思います(いや、単純に順番を間違えただけなんですけどね)。

まとめ

というわけで、1年越しの案件?として、F# から Fortran を扱うネタ記事ができました。これで、既存の Fortran ライブラリを F# から作ったアプリが作れますね…っていうか、誰得な技術情報なのですが、いやあ、やってみたかったということで。皆様、よいクリスマスをッ!!!

カテゴリー: F#, Fortran | 1件のコメント

RealSense 事始め

RealSense App Challenge 2014 – Intel
http://japan.intel.com/realsense/

というのがあって、無事ステップ1を通過して、無事先日 RaelSense の実機が届いたので色々と実験中です。2月末ぐらいまでにアプリを作って提出しないといかんのですが(参加賞っぽい≒数が多いという意味での mini pc ぐらいは貰えるぐらいまでは頑張らんと)、スタートダッシュはできなかった(するつもりはなかった)ので、ちまちまと。

機器自体は、まだ製品化前?かつ、SDKもベータ版なのですが、一通り C++/C#/Java のサンプルが付いていて、ひと通り動かすことができます。開発環境が Windows 8.1 Update 64bit 版 かつ USB 3.0 ポートがある PC ということなので、それなりにスペックの高い PC(あるいはノートPC)を用意しないといけないかなと。

Intel® RealSense™ SDK | Intel® Developer Zone
https://software.intel.com/en-us/intel-realsense-sdk

とはいえ、手元の白 vaio S シリーズで、そこそこ動いているので(顔認識させているときとかの CPU パワー喰いはすごいですが)そこまで高スペックでなくてもよいかもしれません。なお、ツイッターで検索すると RealSense をやっているのは私のほかに @saka_pon さんと @hatsune_ @yukio_saitoh さんとぐらいです。潜在的にはもっといるような気がしないでもないのですが、まあコンテストだからこんなぐらいかもしれません(全世界で3000人ぐらいだから、日本に50人ぐらいいても不思議ではないと思うのですが)。

https://pbs.twimg.com/media/B4JNfSvCcAAlMCF.jpg:large

RealSense で何ができるのか?はさておき、SDK をみてみると、普通の USB カメラでも動く機能ついてきます。Device が RealSense のカメラだけじゃなくて、USB カメラであれば何でもいいので、上記のように表情のトラッキングアプリも動きます。このサンプルは RealSense SDK の中に入っているもので、ソース付きなのでそのまま自作アプリに組み込めます(とはいえ、64bit 限定だしベータ版なのですが)

image

画像データ自体は、PXCMImage という独自形式になっていますが、拡張メソッドの ToBitmap が提供されていて、これをピクチャーボックスに fps 単位で描画することで動画のようにみせています。単純な Bitmap の切り替えなので、文字の重ね合わせとかが楽になりそうで助かります。raw_streams というサンプルに PXCMBitmap クラスがあって、PXCMImage から Bitmap へ変換しています。サンプルのほうも C++ よりも C# のほうが UI がリッチになっている(Unity は持ってないのでわからないです)のが時代の進歩を感じさせます。ちょっと前までは C++ のほうがきれいな UI(あるいは豊富な機能)を用意したものですが、おそらく C# のサンプルを作って C++ サンプルが後追いになっていると思われます。

私の場合は、主にオブジェクトトラッキングとオブジェクト認識のところを攻めてアプリに仕上げる予定なのですが、RealSense SDK 自体のオブジェクトトラッキングで足りない部分は、OpenCV で補います。このときに、C# から使える OpenCvSharp を使うのと、同じように Cv.Mat から Bitmap へ変換できる機能を利用していきます。

同時に、アプリの UI は WPF で作ります。そうすると、文字や他のコントロールとの重ね合わせが非常に楽になります。Visual Studio 上でレイアウトをアレンジできるし、既存の WPF コントロールを使ってエフェクトを作れますからね。その場合も、先の OpenCvSharp にある WritableBitmap の機能や、Bitmap の相互変換機能を使います。

そんな訳で、このあたりの Bitmap の相互変換ができるとアプリ作りがやりやすいので、そのあたりが手を付けていこうと思っているところ。

カテゴリー: RealSense | RealSense 事始め はコメントを受け付けていません

プロ生ちゃん Hidden Object ゲームを作ろう…の途中

プロ生ちゃん Advent Calendar 2014 – Qiita
http://qiita.com/advent-calendar/2014/pronama-chan

の8日目の記事です。Xamarin+F# とダブってしまったので、ゲーム自体ができていません…という訳ではなくて、マスコットアプリ文化祭 2014 もかねて作る予定だったのですが、なんかあれこれと体調が悪くて、できあがりそうにないので、構想と途中経過だけでもつらつらと。

マスコットアプリ文化祭 2014 (Mascot Character Apps Contest)
http://pronama.github.io/mascot-apps-contest/2014/

Hidden Object Game とは?

Online Hidden Object Games | Big Fish
http://www.bigfishgames.com/online-games/genres/15/hidden-object.html

単純に絵に隠されたモノを探すゲームです。ブラウザでもPCネイティブでもあるのですが、リアルっぽい絵の中に、リアルっぽいコインやら壺やら剣やらが隠されているので、探して見つけ出します。リストにある(英語なんだけど)名前のものを探してクリックする単純なゲームなんですが、なぜかブラウザゲームの1ジャンルを占めています。たぶん、探すとそれなりに時間がかかるので暇つぶしにいいのと、ゲームのお試し時間(1時間など)に挟み込んで、お試し時間を食いつぶすのにちょうどいいんですよね。このゲーム方式。
Hidden Object Game を解くアルゴリズム…を考えるのも面白そうなのですが、今回は、Hidden Object を作るほうのアルゴリズムを考えてみます。

たぶん、公開されているゲームは、背景の絵に人の手でちまちまと隠れそうな場所を選んでおいていると思うのですが、それを自動化します…自動化して何かいいことがあるのか?汎用性はあるのか?ってのもあるけど、まあ自動化する方法を考えてみましょう。その経緯で得られるものは多いですからね。

隠れるとはどういうことか?

最初に「隠れる」とはどういうことかを考えておきましょう。Hidden Object では、モノを隠すときに単純に絵に重ねています。半透明になって判別しづらい状態になっています。ちょうど背景の形に沿っていたり、背景の色に揃っていたりします。絵本などのローリーを探せのような探しものは、(人の意志で)あらかじ絵に埋め込まれていますが、Hidden Object の場合は、あらかじめ背景があるところに(人の意志で)見つけにくくなるように重ね合わせをします。
同時に、完全に重ね合わせて隠れてしまってはいけません。きちんと、見つかるように微妙な違いは残しておく必要があります。そうしないと、見つからないかくれんぼになってしまうので、いつになっても終わりになりません。

これが、無造作に渋谷の街並みにプロ生ちゃんを半透明に隠した状態です。半透明にしているだけだから、隠れているといえば隠れているし、無造作に置いているだけなので、隠れていないといえば隠れていません。すぐ見つけられます。

特徴量をみてみよう

この「隠れる」という定義を考えなおしてみましょう。(いきなしですが)コンピュータビジョン的なところでいえば、物がわかる(物体を認識する)という方法、主に「特徴量」というものを使います。モノの写真の角とか辺とかをかき集めて、モノの特徴を拾い出すんですね。コンピューターの目で「特徴量」を拾い出してモノを認識するのであれば、逆に「特徴量」がわからないようにすれば、コンピューターの目にとって、うまく隠れることができるのではないか?ってのが、特徴量を使う発想の元です。既に、手段が目的に代わってしまっていますが(苦笑)、なんか思いついたので試してみたかったのです。

これが背景となる渋谷の画像の特徴量です。いっぱいマルがついていますが、このマルのあるところが、写真の中の特徴的な部分というわけです。約2万点あります。コンピューターの目は(すでに人間の目ではない)、この特徴点を頼りにして、そこに何があるかを調べます。物体の特徴点と比較するわけです。

これが、プロ生ちゃんを置いたときの特徴量の表示です。背景となる部分は変わらなくて…ってことはなくて、FAST で計算したからなのかランダムが入って毎回ちょっと変わるんですよね。うーむ、それはさておき、先の背景だけの特徴量の抽出と、プロ生ちゃんを入れたときの特徴量の抽出を比較して、

  • あまり差がなければ、うまく隠れている。
  • 特徴量の差が大きければ、(コンピュータの目で)見つけやすい

という仮定ができます。

比較をしてみると、

ほら、プロ生ちゃんを置いたときと、置かないときに特徴量の差が、が、が、というストーリーだったのですが、これだと分かりづらいですね。つーか、わかりません…

前後の特徴点の比較は、プロ生ちゃんを置いた場所がわかっているので、その近傍(この場合は、100×100)だけ調べます。透過している背景部分はかわらないはずで、重なっているところの特徴点が違っている状態になる、と予想する訳です。で、その変わっている点が少ない方がうまく隠れている状態で、逆に特徴点がたくさん変わっていると見つかりやすい(隠れていない)と考えることができます。

隠す候補は、回転も含めて 100 点ぐらい用意しておいて、それぞれの特徴量の変化を計算して比較すればよいのです。特徴点のずれ自体は、相関関数を使って計算すればよいでしょう…ってところまでは考えたんですけどね、ちょっとまだ作成中です。

OpenCvSharp を使う

でもって、特徴量を計算したり WPFのImageを扱ったりするのに OpenCV を使っていますが、C# から使える opencvsharp という便利なライブラリがあります。NuGet で取得できるので手軽にプロジェクトに組み込めて便利です。

OpenCV | OpenCV
http://opencv.org/
shimat/opencvsharp
https://github.com/shimat/opencvsharp
NuGet Gallery | OpenCvSharp 2.4.10.20141111
https://www.nuget.org/packages/OpenCvSharp-AnyCPU/

ちなみに、先の特徴量の計算は以下な感じです。OpenCV の中身を弄らないのであれば、CV.Mat でそのまま受け渡しができるので、便利でしょう。実際、カメラキャプチャして画像処理をしているのですが、640×480 程度であれば CVEx.WriteableBitmapConverter.ToWriteableBitmap は 30fps 程度で動きます。

CV.Mat FeatureMatching(
	CV.Mat img1,
	string featureDetectorName,
	string descriptorExtractorName,
	string descriptorMatcherName)
{
	// 特徴点抽出
	var detector = new CV.FastFeatureDetector();
	var keypoint1 = detector.Detect(img1);
	var output = new CV.Mat();
	CV.Cv2.DrawKeypoints( img1, keypoint1, output );

	return output;
}

/// <summary>
/// プロ生ちゃん込みで特徴量を算出
/// </summary>
/// <param name=&quot;sender&quot;></param>
/// <param name=&quot;e&quot;></param>
private void OnClickProNama(object sender, RoutedEventArgs e)
{
	string featureDetectorName = &quot;FAST&quot;;
	string descriptorExtractorName = &quot;BRIEF&quot;;
	string descriptorMatcherName = &quot;BruteForce&quot;;

	// プロ生込みで bitmap に保存
	var path = @&quot;d:temppnpronama.png&quot;;
	SaveCanvas(this.cv, path);
	CV.Mat mat1 = new CV.Mat(path);
	var mat = FeatureMatching(mat1, featureDetectorName, descriptorExtractorName, descriptorMatcherName);
	this.img1.Source = CVEx.WriteableBitmapConverter.ToWriteableBitmap(mat);

	this.imgPN.Visibility = System.Windows.Visibility.Hidden;
	this.imgPN2.Visibility = System.Windows.Visibility.Hidden;

}

そんな訳で、非常に中途半端なのですが、ネタ的には(自分的に)面白いので引き続きやります。普通、特徴量の計算は特徴点の抽出は「目立つ」ところを見つけて、物体を検知するのですが、このパターンは逆に「隠れる」ために、特徴量が変わらないようにする、ってのがミソです。まあ、文中にもあるように、あくまで「コンピューターの目」から逃れる手段なので、「人間の目」から逃れられるかどうか疑問だし、たぶん隠れないだろうなーという予想はしているのですが。

カテゴリー: 開発, OpenCV | 1件のコメント

Xamarin + F# の話をいくつか

Xamarin Advent Calendar 2014 – Qiita
http://qiita.com/advent-calendar/2014/xamarin

の8日目の記事です。

まずは Xamarin で F# を使う入り口を

F# は関数型言語だとか、.NET ライブラリがそのまま扱えるとかという話はさておき(そこが利点だったりするわけですが)、まずは Xamarin で F# を使うときの入り口をみていきましょう。

F# Support Overview | Xamarin
http://developer.xamarin.com/guides/cross-platform/fsharp/fsharp_support_overview/

Xamarin のサイトとしては、この1ページしかありません(苦笑)。これ、F# が導入されたころから1ページしかなくて、その後1年経っても1ページしかないんですね。だからといって虐げられているわけではなくて、Xamarin のカンファレンスのビデオを見ると「F# F# F#」連呼していたりする(英語の合間ですが)ので、それなりに重きを置いている言語です。少なくとも VB に対するそっけなさよりも手厚い感じです。

F# 本家のサイトにも Xamarin との連携ページがあって

Use F# for iOS App Development | The F# Software Foundation
http://fsharp.org/use/ios/

こんな風に勉強会のビデオがあります。この解説をしている Rachel Reese さんが発表しているのは、New York City F# User Group なんですが、所属が NYC Mobile .NET Developers Group ってところで、ここのスポンサーに Xamarin と Microsoft が並んでいます。ちなみに Reese さんは、F# MVP  で Xamarin 社とは無関係です(どちらかというと F# 寄りな人)。

このあたりの関係は、以前書いた

Xamarin.iOS/android+F#で作る関数型アプリ
http://www.slideshare.net/moonmile/xamarini-osandroidf

の参考リンクから辿って行けます。

でもって、F# を使って Xamarin.iOS/Android を作る入門編なページを探す訳ですが「ありません」。これは、Xamarin Studio 自体に F# のテンプレートが導入れて間もないのと(1年位しか経ってない?)、ライブラリのあれこれの整合性が大変だったり、そもそも F# を使っているプログラマ人口が少なかったり(あわせて Xamarin を使っている人口もそれなりに少ないだろうし)ってことで、そういうのがありません。
最初のプロジェクト自体は、先の Xamarin のドキュメントにあるように作成できるようにしてあるのですが、その先がなかなか大変です。

F# と Xamarin を同時に学ぶ…ってのは不可能ではないけれども、同時にやるのは大変なので、

  • F# を学んだあとに、ライブラリとして Xamarin に組み込む
  • Xamarin を使いこなした後で、F# に置き直しておく

というアプローチがお勧めです。

どんなところで F# を使うのか?

Xamarin のサンプルも Microsoft のサンプルも C# が一番充実している(というか、唯一になりつつありますが)ので、C# 以外の選択をする場合にはそれなりに理由が要りますよね。Javascript で書くから Cordova、C# で書くから Xamarin、Objective-C/Swift で書くから Xcode みたいなものです。それぞれの利点と欠点を踏まえたうえで(特に欠点を踏まえたうえで)、組み合わせを選択する落とし穴にはまりづらくなります。

端的に言えば、「C# の苦手な部分」あるいは「F# でないと実現できない部分」を見つけて C# と置き換えるのがベターです。

MvvmCross や Xamarin.Forms を使って MVVM パターンを利用すると、自然と View と Logic をライブラリ単位で分けることができます。PCL を使って分けてもよいし、ターゲットが iOS だけなれば、Xamarin.iOS だけ利用するネイティブのライブラリを作ってわけても構いません。PCL にしてしまうと、使えるライブラリが減ってしまったり、DI パターンを利用する必要があったりするので、さくっと作りたいときに不便なので使い分けをします。

この図で行けば、4パターンが考えらます(全体を F# で書く場合も含めると5パターンになるけどそれは別の機会に)。View に F# を使うときは、PCL の Xamarin.Forms を通す場合と、ネイティブの Xamarin.iOS を直接扱う場合。ロジックに含む場合には、ネイティブのデバイス(カメラやGPS)を触る場合と、全く触らずにロジックだけで完結する場合ですね。

F#単独のライブラリを作る

1番導入しやすいのは、ロジックだけで完結する場合ですね。ロジックだけで完結しているので、NUnit が使いやすいし、他のライブラリを使うわけではないのでテストがしやすくなります。このあたりは、普通に C# のライブラリを作るときと変わりませんね。
計算ロジックとかパズルロジックとかを F# で書いて、ユーザーインターフェースを C# で書くパターンがこれです。パズルロジック自体は、NUnit などを使ってテストしたり、別の UI(WPFとか)を使って作れるので便利です。Xamarin との組み合わせではありませんが、F# + OpenCvSharp の画像フィルタをこのパターンで作ったりしています。

特定のデバイスをF#で扱う

特定のデバイスを扱う部分をライブラリ化しますが、これを F# で作るパターンです。この場合、ネイティブのライブラリが C#(内部的には Objecive-C や Java)で提供されているために、あまり F# を使うメリットは無いように見えるのですが…、実はフィルタ絡みとかイベント絡みを書くときに F# は便利です。パイプライン演算子「|>」を使うのと、カリー化をうまく利用すると柔軟にフィルターが作れます。
あとは、デバイスへのアクセスを F# Interactive で動かせるように単独化させておくと、実験などが楽になります。

Viewを扱う部分を F# で書く

moonmile/XFormsPreviewer
https://github.com/moonmile/XFormsPreviewer

では、Xamarin.Forms の XAML を自前でパースしていますが、このようなコードを書くときに F# は便利です。字句解析とクラス生成あたりが素直に書けるのが F# のよいところです。同じコードは C# でも書けるのですが、かなり冗長になります。この場合、ネックだったのが既存のパーサライブラリを使えない(PCL用のパーサがなかった)ってのがあって、F# で自前で書いています。

Xamarin.formsとカスタムコントロールの話
http://www.slideshare.net/moonmile/xamarinforms-41882310

の中にある、カスタムコントロールなところは、F# で書いても十分有効なところです。データバインドとかカスタムセルのところも作りやすいところです。

とはいえ、ハイブリッド特有の落とし穴がある

これは将来的に直るかもしれませんが(One.NETというスタイルで)、現状では、ネイティブアセンブリと、PCL の各種で使えるライブラリが異なるので、ここかかなりネックになります。多くの場合は、DI として Xmarin.Forms の中からネイティブのUIクラスを使うようにインターフェースを切るか、ネイティブそのものでリビルドをしてしまいます。ソースコードが社内や個人持ちであれば、コード共有してリビルドのほうがいいのですが、NuGet などの配布を考えるとクラス設計をして PCL 化しないといけません。ただし、NuGet が絡むと C# でも F# でも事情は同じで、PCL からネイティブのクラスを触るときに問題がでてきます。そのあたりプロジェクト扱いは、次期の Visual Studio 2015 で変わるので、それに次期?Xamarin Studio がどのように対応していくのか、によって F# で作るライブラリの扱いが変わってくるでしょうね。

カテゴリー: 開発, F#, Xamarin | Xamarin + F# の話をいくつか はコメントを受け付けていません