2018年11月12日月曜日

IIJmio SIM カードが入った iPad Pro (2017) 10.5インチモデルで Apple SIM を使おうとして苦労した話

出張先(米国内)で内蔵 Apple SIM を使用して T-Mobile に接続しようとしたら、できなくて困った。



本来ならここで「データ通信プランを選択」というグループに、トレイに入っている SIM カードから NTT DoCoMo 、 Apple SIM で契約済みの T-Mobile 、そしてその他のキャリアへの新規加入が可能なメニュー選択肢が出るはず。

まずは IIJmio での接続に必要なAPNプロファイルを削除してみる。これが入っているとどちらにせよ T-Mobile で通信できないだろう。削除しても、 T-Mobile や Apple SIM の選択肢は出てこなかった。

次に iOS をリスタートしてみる。残念ながらこれでも改善しなかった。

続いて、 General > Reset > Reset Network Settings でネットワーク系の設定をリセットしてみる。これでも Apple SIM が見えない。困った。

Apple Support アプリから現地のサポートにチャットで相談してみたら、下記のとおりアドバイスをもらった。

・SIMスロットに入っている SIM カードを取り外してみる。
・それでだめならバックアップをとって Factory Reset (ひえー)

SIM スロットには IIJmio (DoCoMo)の SIM が刺さりっぱなし。そういえば前回渡米したときは IIJmio じゃなくて、さくらインターネットのセキュアモバイルコネクトを挿していたはずなので、前回問題なかった時とは状況が違うのは確か。

SIM スロットをイジェクトするピンを持ち合わせていなくて困ったのだが、宿泊先の施設に知っている日本人が泊まっていて(笑)ピンを借りることができた。で、 IIJmio の SIM カードを取り外してみると。。。



おうー。まじかよ! T-Mobile きましたわー。
ということで一件落着。

・IIJmio (DoCoMo) SIM が挿さった状態だと Apple SIM が見えない?状態になる
・この状態だと「データ通信プラン」(英語表記では Celluar Plans)が出てこない。
・SIM カードを抜くと Apple SIM が見える、ことが実際におきた
・出張セットのなかには SIM カード取り出し用のピンを忘れずに入れておくようにしましょう

2017年12月23日土曜日

【第1回 Cpaw AI competition】乱入レポート

この記事は、さくらインターネット Advent Calendar 2017 23日目の記事です。
22日目の記事: 日本初の競技機械学習大会!【第1回 Cpaw AI competition】開催レポート
24日目の記事: (追記予定)

こんにちわ。 hasegaw こと、さくらインターネット 高火力コンピューティングの長谷川です。

今回は、22日の記事にて紹介された第1回Cpaw AI Conpetitionについて、続きってわけでもないのですが、続編をお届けします。同コンペティションを開催したCpawの伊東さんは高火力コンピューティングにチームでアルバイトしてくれていまして、ある日のこと。

「AIコンペティションを開催したくて、場所を探しています」
「え?ウチ使えるよ」

ということで、さくらインターネットの西新宿セミナールームで開催することになりました。当日は台風が接近していたこともあり、参加者が少なくなってしまうのではないかと心配したのですが、悪天候のなか歩留まり6割というのは最近の機械学習系のイベントとしては良い意味で裏切られた気持ちでした。



先の記事のとおり、 Cpaw AI Competition では、さくらのクラウド 12コア・96GBメモリのインスタンス(Ubuntu 16.04)を用いて、与えられたデータセットに対する分類器を生成、分類結果を Web サイトから提出します。提出したスコアはそのまま 1% == 1ポイントとして加算されます。つまり65.2% の分類器をつくれば 65 ポイント獲得できるわけですね。

競技時間は 13:30-18:00 のおよそ 4.5 時間。さくらインターネットの社員(わたし含めて2名)は会場運営支援で現地にいたのですが、 4 時間ボケっとしているのは、ちょっと暇です。と、いうわけで。

「伊東くん、私にも問題解かせてよ」

とお願いして、他の参加者と同じように問題を解いてみることにしました。下記は、実際に問題を解いた手順を再現したものですが、当時書いたコードは既に失ってしまったので、書き直した「再現コード」で解説します。


■ 芸能人ブログ記事の分類問題→絶望

最初に手を出したのは芸能人ブログの分類問題(entertainer_blog)です。データセットは Cpaw オリジナルのもので(本稿執筆のために Cpaw から提供を受けていますが)、 Cpaw の皆さんがあらかじめスクレイプ、1記事1テキストファイルに変換されたものです。ブログエントリの教師データを用いて分類器を訓練し、クラスラベルが与えられていないブログエントリを分類することが目標です。

entertainer_blog/train/
entertainer_blog/train/mamoru_miyano
entertainer_blog/train/mamoru_miyano/10.txt
entertainer_blog/train/mamoru_miyano/1000.txt
entertainer_blog/train/mamoru_miyano/1005.txt
entertainer_blog/train/mamoru_miyano/1021.txt
entertainer_blog/train/sano_hinako
entertainer_blog/train/sano_hinako/1004.txt
entertainer_blog/train/sano_hinako/1008.txt
entertainer_blog/train/sano_hinako/1012.txt
entertainer_blog/train/sano_hinako/1014.txt
entertainer_blog/train/shinozaki_ai
entertainer_blog/train/shinozaki_ai/1003.txt
entertainer_blog/train/shinozaki_ai/1006.txt
entertainer_blog/train/shinozaki_ai/1010.txt
entertainer_blog/train/shinozaki_ai/1018.txt
entertainer_blog/train/shinozaki_ai/102.txt
....

データファイルの内容の例


訓練用データセットは下記のとおりの構成でした。

訓練用データ(ラベルあり)
461 shinozaki_ai
509 uesaka_sumire
397 mamoru_miyano
210 sano_hinako
合計 1577

テスト用データ(ラベルなし;スコア獲得用)
合計 1972

データセットを数ファイル覗いてみると、これらの芸能人が誰なのか正直全然わからないですけども、クラスによっては特定の締め方があったり、顔文字の傾向があったり、ということがわかりました。今回は、このデータセットを手軽に処理する目的で Jubatus を用いることにしました。 Jubatus の場合 ngram を用いた特徴量への変換などが標準で備わっていますので、今回のようなデータセットなら、簡単に「とりあえず」食わせられるからです。

wget http://download.jubat.us/apt/ubuntu/xenial/binary/pool/jubatus_1.0.6-1_amd64.deb
apt install ./jubatus_1.0.6-1_amd64.deb
pip3 install --user jubatus


今回は分類問題なので Jubatus のなかでも jubaclassifier を使用します。以下のようなファイルを作成します。 n=6 にしましたが、ここには強い理由はありません(とりあえずノリで決めました)。既存のサンプルを参考に、設定ファイルに指定して jubaclassifier を起動します。

jubaclassifier はポート 9199 で待ち受けており、 Python で記述する学習&予測プログラムから利用します。


jubaclassifier --configpath jubaclassifier.json


そして訓練用データセットがクラスラベルごとにディレクトリで分けられていること、データセットサイズに対してインスタンスのメモリ容量が十分なことから、下記関数でデータセットを読み込むことにしました。

次のコードが Jubatus を用いてデータセットを分類し、Cpaw AI Competition での提出用CSVフォーマットで stdout に出力するソースコードです。

ここまで準備ができたら、実際にデータセットをロードして、 jubaclassifier を用いてオンライン学習し、テストデータを分類します。ここで、標準出力に表示される結果の例を示します。

0.txt,uesaka_sumire
1.txt,shinozaki_ai
2.txt,uesaka_sumire
3.txt,uesaka_sumire
4.txt,mamoru_miyano
5.txt,mamoru_miyano
6.txt,shinozaki_ai
7.txt,shinozaki_ai
8.txt,uesaka_sumire
9.txt,shinozaki_ai

このデータをコンペティションの採点システムに提出すると、得られていた精度はなんと 30% 以下!!4クラス分類だと完全ランダムでも25%前後になるはずですから、いっそのこと全部 shinozaki_ai ラベルで提出した場合のスコアと大差がない。まったく駄目!!

正直、高火力コンピューティングをお客様に紹介して回ったり、プレゼンして回ったりする立場の私がコレなのは本当に恥ずかしてお客様などに顔向けできないなぁ、と思い、動揺し、死にたくなりました。いっそのこと Cpaw に貸してあげた採点サーバーに root で乗り込んでいって DROP DATABASE クエリを叩き込んでしまいたいという気持ちになりましたが、個人的な感情でそんなことをするわけにもいきません。実は、当日は ngram の n=2 で精度が得られなかったため順番に増やしていって 6 まで上げたのですが、これだけで、精度はあがりません。

一旦あきらめて、とりあえず他のデータセットに取り組むことにします。

■ 泣きそうになりながら、マルウェアURLの分類問題

次に取り組んだのは、マルウェアURLの分類問題です。下記URLで取得できる、URLデータセットが先と同じように1サンプル1テキストファイルとして用意されており、オリジナルデータからラベルが取り除かれたテストデータが正常なURLか、グレイゾーンなURLかを判断することが目標です。

Malware URL
http://malwareurls.joxeankoret.com/

データセットのディレクトリ/ファイル構造
train/normal/
train/normal//1007.txt
train/normal//101.txt
train/normal//1011.txt
train/normal//1013.txt
train/malicious/
train/malicious//0.txt
train/malicious//1.txt
train/malicious//10.txt
train/malicious//100.txt
...

あるデータファイルの中身の例


テキストファイルの中が芸能人のブログ記事からURLにかわり、ラベルが変わっただけで、基本的にデータフォーマットは一緒です。

というわけで、遠慮なく先程の dataset.py と classifier.py に突っ込んでみます。 URL は基本的にアルファベットや数字の集合で、N の値はそこそこ大きい必要があるでしょう。なので N はとりあえず、引き続き 6 ぐらいにしておきます。

先程起動した jubaclassifier は芸能人ブログの学習データを持っているので、ここでいったん同プロセスを再起動しておきます(もっといい方法があるのでしょうか?使い慣れているわけではないので、よくわかっていません)。malware_urls.py を実行した結果がこちら。

採点サーバに送ると、またもや精度は 60% にも及びません(2クラス分類なので全く駄目な結果ということです)。もうだめだー!!!逃げたい!!!

そう思っていたところで、 Cpaw 運営側から採点システムの不具合があり、正確な採点がされていないので,データを再提出するようにという指示。先の芸能人ブログ分類、マルウェアURL分類の結果を再提出した結果、こんな感じになりました。

entertainer_blog: 精度 94.6%
malware_urls: 精度 83.7%

なんだぁ〜〜〜〜。ちゃんと分類できてるんじゃん!本当に焦って泣きそうでしたよ!!よかった。

■ 調子に乗りながら、マルウェア分析の分類問題

次はマルウェア分析問題にとりかかっていきます。このデータセットは下記サイトから入手できる MalwareTrainingSets が先と同様のフォーマット(ただしJSON)に変換されているものです。

Free Malware Training Datasets for Machine Learning
https://github.com/marcoramilli/MalwareTrainingSets

データセットのディレクトリ/ファイル構造
train/APT1/1046.json
train/APT1/1051.json
train/APT1/1063.json
train/APT1/1065.json
train/Crypto/0.json
train/Crypto/100.json
train/Crypto/1000.json
train/Crypto/1002.json
train/Locker/1004.json
train/Locker/1012.json
train/Locker/1037.json
train/Locker/1048.json
train/Zeus/1.json
train/Zeus/10.json
train/Zeus/1001.json

train/Zeus/1005.json
...

あるデータファイルの中身の例


Cpawからデータセットのフォーマットが事実上先程と同じなので、遠慮なく分類器にかけていきます。もしかすると、当日では、JSONを解析して特定の値のみを評価したかもしれません(よく憶えていません)。

得られた結果は以下のとおり。
malware_analysis: 精度 99.6%

実はこのデータセットはある見方をするとルールベースで 100% を達成することができました。しかし、それでも追加のコードを書いたりせずに機械学習で殴っておけば 99% の精度が出せる点が、機械学習のメリットだと思います。

さてここまで entertainer_blog 94.6%, malware_urls 83.7%, malware_analysis 99.6% の精度が出せたので、私のスコアは 94+83+99 で合計 276 となり、二番手グループに大躍進です!! (会場スポンサーですけど)


■ ニューラルネットワークで"ファッションMNI?T"

さてさて!

気分がよくなってきたところで、次のデータセットに取り組んでいきましょう。ここまではテキストのデータセットばかりを選んできましたが、残っているデータセットは「ファッションMNI?T」と「古代文字」のふたつ。どちらかを先に試すか?と思ったら、まずは前者かな、と思いました。 MNIST といえば 28x28 の 10 クラス分類問題で、名前から想像するに同じような要領でいけるのではないか、と思い、データセットを覗いてみることに。



これもボーナス問題ですね!オリジナルの Fashion MNIST データセットでは黒塗りマスクがないのですが、今回のは黒塗りマスクのイタズラがされているデータでした。

これはイケる、という確信を得ます。MNIST同様、28x28のモノクロサイズの10クラス分類。データセットをひと目みるとわかりますが、全ての画像に同一パターンの黒塗りがかかっています。畳み込みニューラルネットワークを使用するとこの黒塗りエッジ部分などが邪魔をするかもしれませんが、このデータを単純に線形結合で入力する場合は、オリジナルのファッション MNIST を 14x14 にリサイズされた状態である、と解釈できるのではないでしょうか。もう、これは 14x14 の MNIST にしか、私には見えません。

この問題をどう解くか、ですが Cpaw AI Competition のレギュレーションでは、イベントで提供された 12コア96GB を使いまくっていいので(畳み込んでいるとあっという間に時間が過ぎてしまいそうですが)線形結合で殴るぐらいの計算リソースと残り時間はあります。また、畳み込むと上にかぶっているマスクが邪魔になるだろうでしょうから、結果が予測できません。なので、線形結合モデルでいくことにします。

とりあえず、Chainerフレームワークをインストールします。

pip3 install chainer

データセットはこれまで通り各クラスがディレクトリで分けられて提供されていましたが、テキストファイルではなく画像なので、データセット読み込みを実装します。普段は cv2.imread() のほうが使い慣れているのですが、cv2モジュールがすぐインポートできなかったので、今回はPILを使ってみました。

以下が Chainer を使ってニューラルネットワークを訓練し、テストデータを予測するためのコードの例です。

このコードを実行し、得られた結果を採点サーバに送信したところ 81% の精度が得られ、私は大会で暫定首位に躍り出ました。(会場スポンサーですけど)


■ これは引っ掛けデータセットな「古代文字」

さて、残りは古代文字データセットです。このデータセットは下記URLから入手できる古代文字画像が、一文字ごと、画像ファイルに分割された状態で提供されました。

文学オープンデータ共同利用センター / Center for Open Data in the Humanities
http://codh.rois.ac.jp/



正直、このデータセットはちらっと見るだけでも 13:30-18:00 のコンペティションの中で扱うデータセットとしては非常に重いです。ファッションMNISTのようにある程度の正規化がされているわけでもなく、さすがに畳み込みニューラルネットワークなどのアプローチで、きちんと回さないと、精度が出ないのではないか?という気がします。

とはいえ、この段階で残り1時間ほど。チャレンジできるところまでチャレンジしましょう。(会場スポンサーですけど)


■ 突然のカーテンコール

……と思ったところで、運営からその時点の暫定順位の発表があり、運営の伊東さんから下記の案内がありました。

「あ、ちなみにこの hasegaw って人は会場スタッフなので表彰対象外です」

というわけで、私の AI Competition は散って終わったのでした。



なお、今回のブログ記事執筆のために作成しなおしたコードでは、下記のスコアが得られました。

entertainer_blog: 精度 94.6%
malware_urls: 精度 83.7%
malware_analysis: 精度 99.6%
fashion_mnist: 精度 81.9%

小数点以下切り捨ての合計スコアは357ですので、当日このスコアが出せていたら、トップに踊りでて Google Home mini を勝ち取っていたかもしれません。😭

後日自分で購入した Google Home mini

もちろん、今回はたまたまデータセットと私のとった手段がうまくはまってスコアが伸びただけしかありません。会場には、スコアを伸ばすことを重きにおくのではなく、フルスクラッチで機械学習アルゴリズムを実装するところからスコアを積み上げていた方もいらっしゃるようで、本当に頭がさがります。

次の機会には、もし会場スポンサーの立場であっても、きちんと参加登録してコンペティションに臨んでみたいと思います。


■ 終わりに

機械学習って、聞いたことがあるけど未だ試していなかったり、もしくはちょっと勉強してみたという方も増えてきているのではないでしょうか。

私も、もともと「機械学習やディープラーニングってすごいなぁ」と思いながら、 IkaLog というスプラトゥーンの画像認識ソフトを作っていく過程で、意図せず、各種機械学習アルゴリズムのパワーを体感して、そこから Coursera の Machine Learning コースを受講した程度の知識しかありません。1年ほどスプラトゥーンの画像データに取り組んだ経験がある以外は、機械学習について凡人レベル、もしくはそこに毛が生えた程度の知識しかありません。

しかし機械学習は、ちょっとモチベーションがあると、その状況なりの使い道や楽しみ方が見つかります。また、今回のような問題で7割8割の精度が出せれば、業務上でも自分の仕事の手間を削減したり、ちょっとした業務効率化で効いたりするものです。さくらインターネットでも、機械学習未経験のデータセンター現地スタッフが独学で Jubatus を用いたオペレーション業務の効率化にも取り組んだりもしています。

Cpaw では、今後とも同様のオンラインイベントやオフラインイベントを開催すると伺っています。機会があれば、このようなイベントにぜひとも参加してみてください。

■ おまけ

過去に参加したアドベントカレンダー

2017年9月4日月曜日

Python 向け OpenCV 3.3.0 (Win32) ビルド済みライブラリのビルドオプション

下記サイトから入手可能な opencv_python-3.3.0-cp36-cp36m-win32.whl の cv2.getBuildInformation() の結果。



General configuration for OpenCV 3.3.0 =====================================

  Platform:
    Timestamp:                   2017-08-05T02:46:14Z
    Host:                        Windows 10.0.15063 AMD64
    CMake:                       3.7.2
    CMake generator:             Visual Studio 14 2015
    CMake build tool:            C:/Program Files (x86)/MSBuild/14.0/bin/MSBuild.exe
    MSVC:                        1900

  CPU/HW features:
    Baseline:                    SSE SSE2
      requested:                 SSE2
      required:                  SSE2
    Dispatched code generation:  SSE4_1 SSE4_2 FP16 AVX AVX2
      requested:                 SSE4_1 SSE4_2 AVX FP16 AVX2
      SSE4_1 (2 files):          + SSE3 SSSE3 SSE4_1
      SSE4_2 (1 files):          + SSE3 SSSE3 SSE4_1 POPCNT SSE4_2
      FP16 (1 files):            + SSE3 SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
      AVX (5 files):             + SSE3 SSSE3 SSE4_1 POPCNT SSE4_2 AVX
      AVX2 (7 files):            + SSE3 SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2

  C/C++:
    Built as dynamic libs?:      YES
    C++11:                       YES
    C++ Compiler:                C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe  (ver 19.0.24218.1)
    C++ flags (Release):         /DWIN32 /D_WINDOWS /W4 /GR  /EHa  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:fast   /arch:SSE /arch:SSE2 /wd4251 /wd4324 /wd4275 /wd4589 /MP12  /MD /O2 /Ob2 /DNDEBUG  /Zi
    C++ flags (Debug):           /DWIN32 /D_WINDOWS /W4 /GR  /EHa  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:fast   /arch:SSE /arch:SSE2 /wd4251 /wd4324 /wd4275 /wd4589 /MP12  /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1
    C Compiler:                  C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe
    C flags (Release):           /DWIN32 /D_WINDOWS /W3  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:fast   /arch:SSE /arch:SSE2   /MP12  /MD /O2 /Ob2 /DNDEBUG  /Zi
    C flags (Debug):             /DWIN32 /D_WINDOWS /W3  /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:fast   /arch:SSE /arch:SSE2   /MP12  /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1
    Linker flags (Release):      /machine:X86  /INCREMENTAL:NO  /debug
    Linker flags (Debug):        /machine:X86  /debug /INCREMENTAL
    ccache:                      NO
    Precompiled headers:         YES
    Extra dependencies:          comctl32 gdi32 ole32 setupapi ws2_32 vfw32 glu32 opengl32
    3rdparty dependencies:

  OpenCV modules:
    To be built:                 core flann imgproc ml objdetect photo video dnn imgcodecs shape videoio highgui superres ts features2d calib3d stitching videostab python3
    Disabled:                    python2 world
    Disabled by dependency:      -
    Unavailable:                 cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev java viz

  Windows RT support:            NO

  GUI:
    QT:                          NO
    Win32 UI:                    YES
    OpenGL support:              YES (glu32 opengl32)
    VTK support:                 NO

  Media I/O:
    ZLib:                        build (ver 1.2.8)
    JPEG:                        build (ver 90)
    WEBP:                        build (ver encoder: 0x020e)
    PNG:                         build (ver 1.6.24)
    TIFF:                        build (ver 42 - 4.0.2)
    JPEG 2000:                   build (ver 1.900.1)
    OpenEXR:                     build (ver 1.7.1)
    GDAL:                        NO
    GDCM:                        NO

  Video I/O:
    Video for Windows:           YES
    DC1394 1.x:                  NO
    DC1394 2.x:                  NO
    FFMPEG:                      YES (prebuilt binaries)
      avcodec:                   YES (ver 57.89.100)
      avformat:                  YES (ver 57.71.100)
      avutil:                    YES (ver 55.58.100)
      swscale:                   YES (ver 4.6.100)
      avresample:                YES (ver 3.5.0)
    GStreamer:                   NO
    OpenNI:                      NO
    OpenNI PrimeSensor Modules:  NO
    OpenNI2:                     NO
    PvAPI:                       NO
    GigEVisionSDK:               NO
    DirectShow:                  YES
    Media Foundation:            NO
    XIMEA:                       NO
    Intel PerC:                  NO

  Parallel framework:            Concurrency

  Trace:                         YES (with Intel ITT)

  Other third-party libraries:
    Use Intel IPP:               2017.0.2 [2017.0.2]
               at:               D:/Build/OpenCV/opencv-3.3.0-vc14-x32-py36/3rdparty/ippicv/ippicv_win
    Use Intel IPP IW:            prebuilt binaries (2017.0.2)
    Use Intel IPP Async:         NO
    Use Lapack:                  NO
    Use Eigen:                   NO
    Use Cuda:                    NO
    Use OpenCL:                  NO
    Use OpenVX:                  NO
    Use custom HAL:              NO

  Python 2:
    Interpreter:                 X:/Python27/python.exe (ver 2.7.13)

  Python 3:
    Interpreter:                 X:/Python36-x32/python.exe (ver 3.6.2)
    Libraries:                   X:/Python36-x32/libs/Python36.lib (ver 3.6.2)
    numpy:                       X:/Python36-x32/lib/site-packages/numpy/core/include (ver 1.13.1)
    packages path:               X:/Python36-x32/Lib/site-packages

  Python (for build):            X:/Python27/python.exe

  Java:
    ant:                         NO
    JNI:                         X:/Java18/include X:/Java18/include/win32 X:/Java18/include
    Java wrappers:               NO
    Java tests:                  NO

  Matlab:                        NO

  Documentation:
    Doxygen:                     NO

  Tests and samples:
    Tests:                       YES
    Performance tests:           YES
    C/C++ Examples:              NO

  Install path:                  D:/Build/OpenCV/opencv-3.3.0-vc14-x32-py36/install

  cvconfig.h is in:              D:/Build/OpenCV/opencv-3.3.0-vc14-x32-py36
-----------------------------------------------------------------

2017年2月8日水曜日

ブートイメージからカーネル、rootfs、configを取り出す

image.ub ファイルからカーネル、rootfs、/proc/configを取り出す

SDSoC 2016.3に含まれる ZYBO 向け Software Platform からカーネル、 rootfs、/proc/config を取り出したかったので取り出した。

そもそも image.ub ってなんだ


ARMで使えるブートローダu-bootが扱うイメージフォーマットらしい。

$ mkimage -l image.ub
FIT description: PetaLinux arm uImage with single Linux kernel and FDT blob
Created:         Fri Nov 18 04:07:34 2016
 Image 0 (kernel@1)
  Description:  PetaLinux Kernel
  Created:      Fri Nov 18 04:07:34 2016
  Type:         Kernel Image
  Compression:  gzip compressed
  Data Size:    8747883 Bytes = 8542.85 kB = 8.34 MB
  Architecture: ARM
  OS:           Linux
  Load Address: 0x00008000
  Entry Point:  0x00008000
  Hash algo:    crc32
  Hash value:   252654ca
 Image 1 (fdt@1)
  Description:  Flattened Device Tree blob
  Created:      Fri Nov 18 04:07:34 2016
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    13962 Bytes = 13.63 kB = 0.01 MB
  Architecture: ARM
  Hash algo:    crc32
  Hash value:   66629950
 Default Configuration: 'conf@1'
 Configuration 0 (conf@1)
  Description:  PetaLinux Boot Linux kernel with FDT blob
  Kernel:       kernel@1
  FDT:          fdt@1


カーネルを取り出す


まずこのイメージからカーネルを取り出す。 mkimage -l の結果から gzip compressed であることがわかっているので、 magic を頼りに探すと 240バイト目から gzip データがあることがわかる。 mkimage の結果からファイルは 8747883 バイトであることがわかる。

$ grep -P -a -b  --only-matching $'\x1F\x8B\x08' image.ub
240:

なので

$ dd if=image.ub of=linux.bin.gz bs=1 skip=240 count=8747883
8747883+0 records in
8747883+0 records out
8747883 bytes (8.7 MB, 8.3 MiB) copied, 6.91697 s, 1.3 MB/s

$ file linux.bin.gz
linux.bin.gz: gzip compressed data, was "linux.bin",
  last modified: Thu Nov 17 19:07:33 2016, max compression, from Unix


カーネルの中から gzip データを取り出す


さらにこのアーカイブの中にrootfsが含まれている。cpioフォーマットで入っているかと思い、cpioフォーマットのヘッダである"070707"をgrepしたら発見... と思ったがハズレだった。これはcpioアーカイブじゃなくてcpioアーカイブを探すプログラムが参照している文字列っぽい。ということは...

$ grep -P -a -b  --only-matching $'\x1F\x8B\x08' linux.bin
6278680:
8588960:
9923536:

gzip のヘッダらしきものが3つ見つかった。まずひとつ目は...

$ dd if=linux.bin skip=6278680 bs=1 | gzip -dc > hoge

gzip: stdin: decompression OK, trailing garbage ignored

toor@gpusv:~/zynq7/extract_initramfs$ file hoge
hoge: Linux make config build file, ASCII text

ASCIIだと!?

$ head hoge
#
# Automatically generated file; DO NOT EDIT.
# Linux/arm 4.6.0 Kernel Configuration
#
CONFIG_ARM=y
CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_MIGHT_HAVE_PCI=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_HAVE_PROC_CPU=y
CONFIG_NO_IOPORT_MAP=y

...config.gz だった。まあ、ついでなので保存。

$ mv hoge config


では次。

$ dd if=linux.bin skip=8588960 bs=1 | gzip -dc > hoge
gzip: stdin: decompression OK, trailing garbage ignored

toor@gpusv:~/zynq7/extract_initramfs$ file hoge
hoge: ASCII cpio archive (SVR4 with no CRC)

toor@gpusv:~/zynq7/extract_initramfs$ cat hoge | cpio -it | head
cpio: Substituting `.' for empty member name
.
dev
dev/pts
etc
etc/opkg
etc/opkg/arch
etc/rpm
etc/rpm/sysinfo
etc/rpm-postinsts
etc/network

今回は間違いなくinitrdイメージだ。

$ mv hoge initrd


目的な達成したけど、3つめはなんじゃらほい。
dd if=linux.bin skip=9923536 bs=1 | gzip -dc > hoge
gzip: stdin has flags 0xce -- not supported


これは有効なgzipじゃなかった。"070707" 同様に gzip をデコードするルーチンが参照している定数かも。

2017年1月19日木曜日

Oculus Rift CV1 に近視レンズを組み込んだ


Oculus Rift CV1 用のレンズアダプターで近視レンズを組み込んだので、久々にブログにまとめようかと。

皆さんの VR ライフ満喫していますか?

実は... 私はあまり満喫できていませんでした。眼鏡男子の私にとって Oculus Rift CV1 の利用それほど手軽ではなかったからです。

普段、私は乱視矯正・近視矯正の両方が入った眼鏡をかけています。例外的に、冬にスノーボードを楽しむ時にはワンデータイプのコンタクトレンズを使っています。このため、 Oculus Rift CV1 で何か VR コンテンツを楽しむにあたっても、 Lucky's Tale 程度のコンテンツなら裸眼で問題ないとはいえ、 EVE: Valkyrie にょうな UI であったり、細かい文字を読み取らないといけないようなコンテンツではコンタクトレンズを装着しないと楽しめない状況でした。また、私が利用しているのはワンデータイプのコンタクトレンズです。ふらっと Oculus Rift で遊ぶときにワンデーコンタクトを消費するとなると、心理的なハードルはさらに高くなります。

CV1 用レンズアダプターを入手!

そんなことを思っていたら、Oculus Rift CV1 ヘッドセットにメガネ用のレンズを装着し近視矯正を可能にするアダプターの 3D モデルデータを見つけました。

このレンズアダプターは Oculus Rift CV1 にぴったりとはまるようにデザインされていて、レンズには、一般的な眼鏡用のレンズが利用できます。当初より公開されている、オリジナル版のアダプターでは、Zenni Optical の #450021 用に作られた、直径 40mm の円型の眼鏡用レンズを装着できます。

これをどこかでプリントしてもらうか、プリントしてもらうなら送料ケチるために複数オーダーしたほうがいいかなとか色々考えつつ、手を出せていなかったのですが……。もう半年以上前に見つけたこのレンズアダプターですが、最近 3D プリンターを購入したという知人がこのアダプターをプリントしてくれたので、ついに実物を手に入れることができました。


写真は見やすい白い樹脂でプリントしたものを掲載しましたが、実際に CV1 に取り付けたものは黒色のアダプターです。

レンズを入手するための方法は?

そして、次のチャレンジは、「眼鏡のレンズをどうするか」です。今回入手したアダプターは先のとおり Zenni Optical #450021 と互換性があります。このアダプターに対応するレンズを入手する方法として、まずは下記2パターンが考えられます。


  1. 同フレームのみ購入して、レンズは日本で作る
  2. 同フレームとあわせて、レンズも購入する

ずっと悩んでいたのですが、今回は結局、後者「レンズを購入したらフレームもついてくる」という形で入手することにしました。

はじめての通販眼鏡オーダー

次の問題は、いままで眼鏡購入は街のメガネ屋に依頼して作ってもらっていて、通販で眼鏡のレンズなんて買ったことがない、という点です。このため、過去に購入したコンタクトレンズや眼鏡のパラメータを参考にオーダーすることになります。

コンタクトレンズの度数でオーケー

先述のとおり、私は近視矯正用のコンタクトレンズを使用しているので、そのコンタクトレンズを見ることで自分が必要とする近視矯正のパラメータがわかります(というか何百回もコンタクトレンズを使っているので、近視の強さはもう憶えてしまっています)。手元のコンタクトレンズによる近視矯正のパラメータは下記のとおりでした。

  • 左目 -3.25
  • 右目 -2.75

私のコンタクトレンズは乱視矯正タイプではありません。コンタクトレンズは乱視矯正が入るとモノが分厚くなります。個人差がありますが、私の場合、装着感が悪くなり、外れやすくなります。コンタクトレンズを購入するにあたって色々相談したり試した結果、「乱視矯正をせず、近視矯正だけにする」ことにしました(ただし近視矯正を多少強めに入れています)。過去12年ほど、ずっと同じ度数でワンデータイプのコンタクトレンズを使っておりこのコンタクトレンズで遠くにいる仲間の姿、顔や、トラック、遠くの看板など、アウトドアで必要十分な視界が得られることがわかっており、CV1でも問題ありません。このコンタクトレンズと同じ度数の眼鏡レンズを CV1 に入れれば問題ないはずです。

IPDは、眼球と眼球の距離

IPDは左右の眼球の中心の距離を示すパラメータのようです。コンタクトレンズは眼球自体に装着するので IPD の値がわからないのですが、 Ocuus Rift CV1 のセッティングでは 62mm がもっともはっきりして見えるほか、定規で自分の眼球の距離を測ってみてもおよそ 65mm ぐらいでした。「指定できるIPDの値がジャストでない場合は狭い方の値を選べ」ということですし、 CV1 で 62mm という数値が出ていたので、今回は 62mm で作成することにしました。

眼鏡購入時の伝票やカルテからも、必要となる値はわかるはず

眼鏡を持っていても自分の左右の目の矯正パラメータを憶えていることはそうそう無いと思いますが、眼鏡を作ってもらったときの資料が残っていれば、そこに矯正のパラメータが書かれているので、確認することができます。もしくは、眼鏡を作った眼科やお店に問い合わせれば、カルテが残っているはずです。

私がオーダーしたレンズのパラメータは?

先述の近視矯正のみであれば、Zenni Optical の眼鏡オーダー時に下記のパラメータでオーダーすれば十分です。CYL、Axisは乱視矯正の場合のパラメータですので、近視矯正だけの場合はゼロで問題ないのだと思われます。



一般的に眼鏡のレンズは矯正がつよいほどレンズが分厚くなり、高価なレンズほど値段が安くなります。つまり安価なレンズで矯正を強くするとレンズが太くなります。今回、私は 1.57 Mid-Index Single Vision のレンズでオーダーしました。

Oculus Rift CV1への装着感、見え方など含めて、私の度数ではこの設定で特に問題はなさそうです。近視が私より大幅に強い人は、薄い購入レンズを選ぶか悩まれるかもしれません。

コーティングは下記のみにしました。どうせ VR 用ですし。
  • Anti‐Reflection Coating
  • Standard anti‐reflective coating

価格は?

レンズ(+フレーム)代金は14.90ドル、日本への送料が9.95ドルでした。クレジットカードへの最終的な請求金額は下記のとおり、3000円弱でした。



配達されてきた

オーダーしたレンズ(+フレーム)は香港で製造され、日本に向けて出荷されたようです。封筒に眼鏡ケースを入れて送られてきました。(写真は後でとったもので、レンズは取り外し済みです)



ちなみに常用している日本ブランドの眼鏡と比べると、ノーズパッドのは幅に大きな差があります。日本人は鼻が低いですもんねー。



出来上がった眼鏡の状態で見え方に問題がないかを確認しても、とくに問題はありませんでした。

重要! レンズを外す前に

レンズを外す前に、コーティングを痛めないようなメンディングテープや付箋をレンズにはり、上下がわかるようにしておくことをお勧めします。
  • 右目レンズか、左目レンズか
  • レンズのどの部分が上か(円形レンズなので方向がわからなくなる)
特に、乱視矯正レンズだと方向は絶対に大事なので、やはり方向がわからなくならないよう、特に注意してください。

実は、私の場合この眼鏡に対応できる精密ドライバーが手元になかったので、普段お世話になっている眼鏡ショップでレンズを外してもらいました(店舗によっては嫌がられるでしょうから、これが当たり前だとは思わないでください!)。この際、どちらが上であったか等を示す印をつけないまま外してもらった都合、購入時点でどの部分が上だったかは分からなくなっており、反省点です。(IPDがおかしいことになっているかも)

CV1への装着

まず、眼鏡のレンズ2枚を装着します。レンズアダプターに必要以上の力をかけないように注意しながらはめこみます。一度はめ込んでしまえば、アダプターからレンズがすぐにポロッと落ちることはないでしょう。少しゆるく感じるかもしれませんが、CV1に組み込めば、もっと安定します。

CV1の顔に当たるスポンジ部分は、その樹脂フレームと一緒に、Rift本体から分離できます。液晶側(スポンジがついていない方)からレンズアダプタの下のレール部分をはめこみます。

Thingverse に投稿されている写真より

そして、同パーツとレンズアダプタをOculus Rift CV1本体にはめ込めば取り付け完了です。

利用感

映像の見え方としてはバッチリです。

普段利用している眼鏡を外さないといけないのはまだまだ不便ではあるのですが、それでもコンタクトレンズなしで CV1 を装着すれば VR 内で表示された小さな文字まできちんと読めるので大変便利です。実はまだ Touch をオーダーしていないのですが、今後 Touch を入手するのが楽しみになりました。

まとめ

普段から視力矯正が必要な人が VR ヘッドセットをかぶるのはちょっと大変です。でも、 CV1 に今回紹介したレンズアダプター、そして安く作れるレンズを組み合わせることで、 VR ライフがより身近なものになります。

私のような、眼鏡を常用しており、結果として Oculus Rift CV1 から遠ざかってしまっているオーナーの方もいるかと思います。そんな方には本アダプターがとても役にたつかとと思います。

2016年11月20日日曜日

私家版PYNQ FAQ(購入前)

先日オープンソースカンファレンス2016東京でIkaLogを出展した際、PYNQ-Z1をIkaLogのデモ用ハードウェアに利用したのですが、その際に色々と質問されることがありました。今回はPYNQ-Z1がどのようなものなのかについて、私の偏った視点から紹介します。

PYNQって何ですか?


PYNQというのは、基板やLSIパッケージではなく、Xilinx社が提供する「Jupyter Notebookから使えるFPGAデモシステム」を指しています。以下はXilinx社が公開しているPYNQプロジェクトの概要を引用したものです。

PYNQ is an open-source project from Xilinx that makes it easy to design embedded systems with Zynq All Programmable Systems on Chips (APSoCs). Using the Python language and libraries, designers can exploit the benefits of programmable logic and microprocessors in Zynq to build more capable and exciting embedded systems. PYNQ users can now create high performance embedded applications with

  • parallel hardware execution
  • high frame-rate video processing
  • hardware accelerated algorithms
  • real-time signal processing
  • high bandwidth IO
  • low latency control

See the PYNQ webpage for an overview of the project, and find documentation on ReadTheDocs to get started.

PYNQ-Z1って何ですか?


PYNQ-Z1はDigilent社が販売するARM搭載FPGAボードであり、Xilinx社のPYNQに対応しています。以下はDigilentが紹介しているPYNQのスペックです。

ZYNQ XC7Z020-1CLG400C:
  • 650MHz dual-core Cortex-A9 processor
  • DDR3 memory controller with 8 DMA channels and 4 high performance AXI3 slave ports
  • High-bandwidth peripheral controllers: 1G Ethernet, USB 2.0, SDIO
  • Low-bandwidth peripheral controller: SPI, UART, CAN, I2C
  • Programmable from JTAG, Quad-SPI flash, and microSD card
  • Artix-7 family programmable logic
  • 13,300 logic slices, each with four 6-input LUTs and 8 flip-flops
  • 630 KB of fast block RAM
  • 4 clock management tiles, each with a phase-locked loop (PLL) and mixed-mode clock manager (MMCM)
  • 220 DSP slices
  • On-chip analog-to-digital converter (XADC)

Memory:
  • 512MB DDR3 with 16-bit bus @ 1050Mbps
  • 16MB Quad-SPI Flash with factory programmed globally unique identifier (48-bit EUI-48/64™ compatible).
  • MicroSD slot

Power:
  • Powered from USB or any 7V-15V source (see recommended products)
  • USB and Ethernet:
  • USB-JTAG Programming circuitry
  • USB-UART bridge
  • USB OTG PHY (supports host only)
  • Gigabit Ethernet PHY

Audio and Video:
  • Electret microphone with pulse density modulated (PDM) output
  • 3.5mm mono audio output jack, pulse-width modulated (PWM) format
  • HDMI sink port (input)
  • HDMI source port (output)

Switches, push-buttons, and LEDs:

  • 4 push-buttons
  • 2 slide switches
  • 4 LEDs
  • 2 RGB LEDs

Expansion Connectors:

  • Two standard Pmod ports
  • 16 Total FPGA I/O
  • Arduino/chipKIT Shield connector
  • 49 Total FPGA I/O
  • 6 Single-ended 0-3.3V Analog inputs to XADC
  • 4 Differential 0-1.0V Analog inputs to XADC

搭載されているはXC7Z020-1CLG400Cというもので、デュアルコアのARMプロセッサが搭載されたFPGAパッケージです。そこにLEDやスイッチ、Arduino互換のペンヘッダ(メス)、HDMI入出力、オーディオコーデック(コンピュータエンジニア的にはサウンド用DAC/ADCといったほうがピンときそう)、Digilentが提供する拡張基板が接続できるPMODヘッダなどが搭載されています。

SDカードスロットが搭載されており、ここからLinux環境をブートしてLinuxマシンとして利用できます。ARMプロセッサにイーサネットポートとUSBホスト用コネクタが接続されていますので、この部分は組み込みARMプロセッサとしても利用できます。

Raspberry Pi とのARMプロセッサの比較は?


CPU

  • ZYNQ: ARM7 2cores、650MHz
  • Raspberry Pi 3: Cortex A53、4 cores、1.2GHz

Memory

  • PYNQ: DDR3 512MB
  • Raspberry Pi 3: LPDDR2 512MB

GPU (Framebuffer)

  • PYNQ: なし
  • Raspberry Pi 3: あり

H.264/MPEG2ハードウェアエンコーダ/デコーダ

  • PYNQ: なし
  • Raspberry Pi3: H.264デコード、エンコード(追加オプション)、MPEG2(追加オプション)

ネットワーク

  • PYNQ: イーサネット
  • Raspberry Pi 3: イーサネット(有線、無線)


PYNQ向けの設計・開発に必要なソフトウェアは?


ロジックの設計Xilinx Vivado HL Design Design Suite(Eclipseのような設計環境)のWebPack Editionが無償で利用できます。最近は、無償ライセンスでも機能制限が緩くなっており、評価ボード上のXilinx FPGAパッケージ(最上位のVirtexを除く)を相手に開発する程度であれば不自由なく使えるようになりました。高位合成についてもVivado HLS が 2016.2 あたりから無料で利用できます。ただし、WebPack Editionはツール利用状況の統計情報がXilinx社に吸い上げられます。

Xilinx Vivado HL Design Suite によってFPGA向けのビットストリーム(コンピュータのバイナリファイルに相当)生成処理は非常に重いため、できるだけ高クロック多コアで快適な開発環境(Linuxを強く推奨、もしくはWindowsでも利用可能)が必要になります。Vivado HL Design Suiteはインストールにおよそ20GBの空き容量が必要です。

PYNQで提供されているビットストリームは現在バージョン2016.1向けになっています。より新しい2016.2、2016.3も提供されていますがPYNQのプロジェクトを実行できませんのでPYNQ前提でVivado Design Suiteをインストールするのであれば2016.1をインストールすることをオススメします。なおディスク容量があれば複数バージョンをインストールすることも可能です。


PYNQどこで買えるの?いくら?

Diglientのサイトから購入できます。
http://store.digilentinc.com/pynq-z1-python-productivity-for-zynq/

本稿執筆時点で通常価格229ドル、学生向けには65ドルで販売されており、一人一台までの制限があります。送料が5000円近くかかるそうなので購入時は複数の方でまとめてオーダーし小口数をまとめてもらおうとしている方々もいるようです。経験上オーダーを確定してから2〜3日で日本まで届きます。

購入する場合には、オシロスコープをお持ちでない方には、Analog Discovery 2の同時購入がをオススメしています。AD2はUSB接続し利用できるオシロスコープ/ロジック・アナライザなどとして利用でき、FPGAのほか各種電気回路を作ったときに波形を見るのにも使えるからです。アカデミック対象であれば割引がありますし、Analog Parts Kitは学生による同時購入に限り無料で販売してくれるようですのでぜひ入手してください(私は持っていません)。

オシロやロジアナ皆無でFPGAや電子回路をいじるのはprintfデバッグすら封印して一発で複雑なプログラムを完成させようとするようなものです。

私が持っているのは初代Analog Discoveryですが、実際持っているとすごい便利なのでとってもオススメです。


2016年10月16日日曜日

PYNQを買ったので遊んでいる(Project Inq)

久々にFPGAいじりをしています。

今回入手してしまったのはPYNQ。Xilinx Zynq7020シリーズを搭載した評価ボードで、あらかじめ用意されたイメージをSDカードに書き込んであげればJupiterからWebブラウザ経由でもいくらか操作を試せるというお手軽さがウリ。



届いたPYNQのパッケージ

秋葉原の職場に送ってもらったので、受け取ったら早々と部品やでヒートシンクと熱伝導シーツを調達。

SDカードにイメージを焼いて起動したら、当然とはいえ、普通にヘッドレスなARM7 Linuxマシンとして起動してきた。OSはUbuntu 15。 OpenCVは 3.1 で、FFmpegサポートも入った状態でコンパイルされている。……これは色々と便利なのでは?

試しにIkaLogでビデオファイルを解析させてみたら、あっけないほど簡単に動いた。

PYNQにはビデオキャプチャ利用を想定したHDMI Inputポートがあるので、これでキャプチャできるかは大変興味があるところ。Jupiter上でOpenCVの顔認識をするコードを途中まで実行したら、WiiUの画像がキャプチャできた。



ただしPYNQのbase.bitではDDCの応答内容に問題があるのかWiiUからビデオ信号が出てこない。このためHDMIマトリックススイッチやスイッチャーなどの機械を挟んでいる。また、720pだと色々安定していないような感じ……。過去に試していたとき、ZYBOではDigilentのdvi2rgbのEDIDを書き換えたらWiiUの信号を直接、安定して食えるようになったので、そのときの成果を持ってくれば解決するだろう。だいたい解決策は見えているので後回し。ちなみに以前ZYBOで実験していたときの写真がこちら。


Jupter で操作した内容を IkaLog の映像インプットとして使えるようクラスを追加して、とりあえずだけども対応完了。
https://github.com/hasegaw/IkaLog/commit/5b6b9ce55e1ae32e57c2dd6f05ae20aa00c9b3fd

HDMIのキャプチャは実現できたが、PYNQにはHDMI Outputもあるので、こちらにパススルーすると、PYNQがIkaLogマシン+ビデオキャプチャ+HDMIスプリッタを兼ねるという、いままでIkaLogを利用するにあたって必要となる3つのアイテムをワンボードで実現できることになる。

Pynqのドキュメンテーションを読んでいると、じつは上記の設定でHDMIパススルーも実現できていることがわかった。上記の設定を行うとOut側がIn側のバッファからデータを受け取るようなかたちでパススルーしてくれる(プロセッサは通していないと思う……フレームバッファは通しているかも?)

というわけで、数時間でできちゃったIkaLog+PYNQ(キャプチャ機能+映像のみスプリッタ機能)。

Pynqで動くIkaLog、Project Inqと命名。Pynqの利用用途として思いついてはいたけども、思った以上に簡単に実装できてしまった。ここまでの成果については下記 WIki ページを見ていただければ再現できるはず。
https://github.com/hasegaw/IkaLog/wiki/en_Installation_Pynq

これをしばらく動かしてみるといくつか課題が見えてくる。

一つ目の課題は、HDMI Outputから出力された映像がたまに縦にずれたりする。たぶんHDMI映像の伝送が、ARMのDDR3メモリに置かれたフレームバッファを介していて、IkaLogが走っているとメモリ帯域やバス幅が足りなくなるんじゃないかと疑っている。

二つ目の課題は、HDMIのスプリッタ機能といっても HDMI 信号を音無しの DVI 信号としてピクセル情報に落とし、それを DVI 信号として HDMI ポートから出しているだけなので、音が消えてしまう。もちろんレイテンシの問題もあるし、キャプチャ機能はそのまま使うとしても、 HDMI Input から入ってきた信号をできるだけ忠実に HDMI Output に出力するよう変更したい。

Xilinx FPGAなのでHDMIのシリアル信号をISERDESE2で受けて、出力するときはOSERDESE2で送信している(はず)。これらを直結すればナノ秒レベルのディレイでシリアル信号をそのまま伝達できるだろうけど、ビデオキャプチャ機能も必要なので、dvi2rgb IPと共存することは考えないといけない。

とりあえずPYNQについてきたbase.bitは忘れて、dvi2rgb -> rgb2dvi でパススルーするデザインを作ってみた。



WiiU の信号が直接映らないのは相変わらずだけども、画像がたまに縦に1ドット間延びするような現象は解決した。ARMプロセッサ側のDDR3メモリを介さずに、受け取った信号をそのまま送出しているからだろう。

でも、やはり音のデータは消えてしまっている。

手元に高速ビデオ・インターフェース HDMI&DisplayPortのすべて という書籍があった。


これを読み返してみると、オーディオ信号はVSYNC直後のブランク期間などに入っているとのこと。ここが現状どうなっているかを調べると、色々解決しそう。 dvi2rgb がブランク期間中の信号を捨ててしまっているのではないかという想像だ。もし信号が捨てられていない事が分かればラッキーで、今度は送出側 rgb2dvi が信号を捨てていると考えればよさそう。

Integrated Logic Analyzer を追加して信号を眺めてみる。





案の定 dvi2rgb がブランク期間中の信号をゼロでマスクしているようだ。この 000000 になっているところに、本当はオーディオ信号も乗っているはず。ここにあるはずの信号も含めて rgb2dvi の OSERDESE2 に流し込んであげれば、きっとオーディオ含めてスプリッタとして動作してくれるだろう。

とりあえずの調査はここまで。