2013年12月28日土曜日

RasPi+OpenCV+WebCamera

Raspberry PiにUSBカメラを接続してOpenCVで撮影してみました


とりあえずこんな感じになっています

流れとしては
10行目)カメラを探す
12行目)ポインタアドレスを表示(デバッグ用 0位外であれば正常という判断)
14行目)ヌルポインタ(カメラが見つからない)以外であれば処理
15-16行目)デフォルトの画面解像度を獲得
20行目)画像をキャプチャ
21行目)画像を保存
23行目)保存した画像をsystem関数を使いscpで画面の有るマシンに転送
25-26行目)構造体を解放
だと思います(てきとーにそれらしい関数を引っ張ってきてるだけなので微妙

僕の環境はRasPiに画面が無いので、scpで他のマシンに飛ばしていますが
RasPiに画面が接続されているなら23行目及び4行目は削除しても問題ありません


コンパイルは
$ gcc hoge.c `pkg-config --cflags --libs opencv`
で通ります
めちゃくちゃ時間かかりますが。。


当初はRasPi用カメラモジュールを使おうかと思って、可視光のモジュールも購入済みですが
raspistillが地味に面倒なのでOpenCVを使ってしまいました
あとOpenCVだといろいろ参考になりそうな情報が多い というのも理由です


今のところカメラモジュールを使って何かをつくろうというネタは2個ほどありますが、優先度はかなり低いので気分転換に進める 程度になりそうです
その前にOpenCV本も1冊買っておかないと(ネット情報だと頭にはいらない性格)(本を買っても読まない性格だけど)


いろいろやりたいことはありますが、優先度が低かったり、恐ろしく面倒だったり、高コストだったり、それらのフルコンボだったりでいまいちやる気が出てこない今日このごろです

SDR?

かなり前に買っていた、SparkfunのSDRシールドを試してみました
http://strawberry-linux.com/catalog/items?code=18193


スイッチサイエンスより数円高い程度でアンテナとコネクタが付属しています
このシールドはすでに製造終了しています

サンプルはSparkfunのページからダウンロードできます
https://www.sparkfun.com/products/retired/10342

Documentsの最後にGitHubへのリンクが有りますが、GitHubにはEAGLEファイルがあったりくらいです
Arduino Libraryリンクからライブラリを落とす必要があります

ストリナで買った時の構成は
1)Sparkfunでよくある赤っぽい袋に入ったシールド
2)ピンヘッダ4個
3)バーアンテナ
という感じでした
おそらくスイッチサイエンスで買った場合は1のみで、2と3は自分で用意する必要があったと思います

自分で実装するのはコネクタとバーアンテナ
それからついでにワイヤアンテナもつけておきます
このSDRの受信帯域が64-108MHzで、4分の1波長では70cmから120cmといったところです
ということで今回は1m程度のワイヤをつけておきました

試しに使用したサンプルはライブラリに入っているものです

Arduinoにプログラムを書き込んだら適当なシリアルターミナルで接続します
操作は
8)音量を上げる
2)音量を下げる
4)シーク(周波数下げ)
6)シーク(周波数揚げ)
M)ミュート
U)ミュート解除
S)ステータス
という感じです
ミュート操作以外はテンキーを想定しているっぽいです

setupのなかで tuneFrequencyで最初の周波数を設定できます
引数は10kHz単位です
僕はラジオふらのの77.1MHzにするため、7710を設定しました

このラジオモジュールは出力インピーダンス10kOhmと非常に高く、ハイインピーダンス受けのアンプが必要になります

で、ちゃんとスピーカーを接続して電源を入れたところ
ノイズしか聞こえない!!
うっすらとなにか聞こえてきますが、僕の部屋ノイズ多すぎ

持ち運びできるHighZi受けなアンプが手持ちに無いため、ノイズの少ない環境に移動して試すのは難しそうです
次の課題はこの辺りですね
あと自室のノイズを減らす努力も…

2013年12月22日日曜日

GTKでメニューバー

最近、GTK本を買ったので、色々遊んでいます
といってもまだ第2章の最初の方までしかやっていませんが

で、Nexus7+Ubuntu13.04にGTK2.0を突っ込んだので、非常に可搬性の高いGTK環境ができたため、主にNexus7で試しているのですが、メニュー周りがどうしても動きません

で、色々試していたのですが
結論から先に示すと
最近のUbuntuはWindowsのようなそれぞれのウインドウ上ではなく、MacOSのような、上に表示されるような感じになっているようです

しかも表示されるのがマウスオーバー時限定なので、気がつくのに時間がかかった という感じでした
(通常はこのように何も表示されていない)

Nexus7の画面解像度だとウインドウ上のボタンはタップできますが、上の方にあるメニューは小さくて操作できません
なのでしばらくメニュー周りは放置になりそうです


あと、Nexus7をスリープに突っ込むと、復帰時にタッチパネルの反応が悪い気がします
ざっくり説明すると、スクリーンキーボード以外ほとんど操作できなくなります
スクリーンキーボードは問題なく操作できるので、端末からsudo rebootを叩けばちゃんとタッチが反応するし、端末から操作できることしかやらないならそもそもタップの反応が無くても問題ないわけですが なんだかなぁ という感じです
タッチパネル周りのモジュールをスリープから復帰後にリセット みたいなことができれば便利かも
Ubuntuを起動した時に「エラーが発生しました」的なダイアログが出る以外は結構安定して動いているので、その周りさえ解決できれば結構便利そうです

2013年12月16日月曜日

Nexus7にUbuntu13.04

今更な感じもしますが、手持ちのNexus7にUbuntuを入れてみました

そもそもNexus7を買った理由が
「iPhoneもiPadもKindleも有るなら次はAndroidだろ」
という短絡的な発想で
札幌に行った時に立ち寄った中古PC屋でNexus7が置いてあったからなわけですが

ArduinoDoroidoとか、Processingとか、KitKatとか とりあえずひと通りAndoroidoで動く遊びは試したのと、Android自体はほとんど使っておらず、Kindleくらいしか入れていなかった というのもあります
なのでデータ移行とかも気にせずに「試してみるか~」という衝動でUbuntuを入れた次第です

今回は
http://unizoff.net/blog/315
を参考にしました
イメージのDLに多少時間がかかりましたが、それ以外はあまり問題なくサクッとインストール出来ました
さすがKitKatです 他のOSをインストールするのもサクサク(関係ない


とりあえず、一部タッチ操作が不安定だったり、1280x800という解像度のせいでアイコンが小さくタップしづらかったり と言うのはありますが 一応動いています
もちろんUSBメモリやUSBマウスなども使えます
デスクトップ版Ubuntuなので、通常のUbuntuと同様の操作が可能です

GCCは最初から入っており、G++もapt-getでインストールできます
SSHも同様にインストールすることができ、他のPCやiPhoneなどから操作することができます

GTK2.0はとりあえずWindowの表示とButtonの動作だけは確認しました

しかしOpenCVは動作が微妙で、そもそもOpenCVはIntelが作っているため、ARM版は結構面倒らしいです
ただ全く使えないわけではなく、ちゃんと設定してコンパイルすれば使えるっぽいです
Webカメラもdmesgを見る限りちゃんと認識しているので、画像処理とかもできそうです


さて、タブレットにUbuntuを入れた時におそらく一部の紳士淑女の皆様が一番気になる件
遊べるのか!?

ということについてですが
結論から言うと ダメです><


いくらデスクトップ版とは言え、そもそもOSがARM版なのでFlash Playerがありません
これは艦これがHTML5等に対応するorAdobeがARM版Flash Playerを作る のどちらかを行う必要が有るため、一両日中に対応するのは不可能でしょう


そして、組み込み屋として結構気になるFT232のサポートですが
コレも不可のようです
FTDIはLinuxのドライバを作っていて、カーネル2.4(?)の頃にOSに組み込まれましたが、ARM版のドライバは作っておらず、そのためNexus7に入れたUbuntuからFT232を使ったシリアル変換モジュールは使えません

OpenCVやFT232など、Ras Pi(Raspbian)では動くのにUbuntuでは動かない というのが結構あります
この辺りもっと詳しく探せば動くようになるのかも

とりあえず目安として GTKのような比較的高レベルなライブラリは問題なく動くようです
しかしOpenCVやドライバ等の低レベルへのアクセスを要求するライブラリは動作しないようです


ソフトウェアとしては上記のような問題はありますが、GTKで遊ぶ程度なら十分に使えると言えると思います

しかしハードウェアとしてはまだ微妙なところで、例えば外付けキーボードやマウスがあったほうが快適に操作できます
動作がもっさりしてるのは諦めるとして、タッチパネル周りがもう少し反応が良くなれば使いやすいなぁ という感じです

あと、まだあまり動作が安定しておらず、結構落ちます

まぁ安定性を求める用途などに使うようなシロモノでもないので、総評としては「使える」でしょう
もうちょっと遊んでみたいと思います

2013年12月12日木曜日

OpenCVでキャプチャ

基本的なコードは前回のエントリ参照

画像を獲得するには
IplImage *img = cvQueryFrame(capture);
で画像のポインタを受け取る

保存するには
cvSaveImage("img.png", img, 0);
とする
Webのサンプルを見るとcvSaveImageの引数は2個なんだけど
これはC++で使う前提で、Cだと最後まで引数を指定する必要がある

ファイルのフォーマットはファイル名の拡張子で識別される
bmpとかpngとか、たいていは対応してそう


ノイズとか解像度はカメラによって異なるので、綺麗な画像が欲しければちゃんとしたカメラを探したりとかする必要がある
あとカメラによって解像度が違う とかの可能性もあるので、ちゃんと動くプログラムを作るならその辺りも作りこむ必要がある
(それが嫌でRasPi用のカメラを買ってみたりしたのだけど)

一旦IplImageになってしまえば顔検出とか色々できるので、煮るなり焼くなり好きにできる

RasPiでWebカメラ

今回はラズパイ用カメラじゃないです

前回の続き OpenCVを使ったプログラムのコンパイル方法
$ gcc main.c `pkg-config --libs opencv`
でa.outが作成される
ちょっと時間がかかるんで頻繁にコンパイルしてエラー吐かせる とかはむりぽ

テストコード
      1 #include <opencv/cv.h>
      2 #include <opencv/highgui.h>
      3 #include <ctype.h>
      4 #include <stdio.h>
      5
      6 int main(int argc, char **argv) {
      7     const int cCameraNum = 0;
      8     CvCapture *capture = 0;
      9
     10     capture = cvCreateCameraCapture(cCameraNum);
     11
     12     printf("capt  :%d\n", (int)capture);
     13     printf("width :%d\n", (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH));
     14     printf("height:%d\n", (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT));
     15
     16     cvReleaseCapture(&capture);
     17
     18     return(0);
     19 }
     20
Webカメラが接続されていればcaptureのポインタと、現在設定されているカメラの解像度が出力される
OpenCVがカメラを検出できなければポインタにはnullが入り、解像度も0になる
ちなみにこのカメラにRasPi用カメラはカウントされない
手持ちのUSBカメラは認識された

画像の獲得とかはこれからやる

ちなみにWebカメラのドライバとかは不要 接続するだけで使える
USBホント便利

2013年12月11日水曜日

RasPiのカメラ

RasPiのカラーカメラを買ってみた
RSで買うものが色々あったのでついでに という感じ
このエントリは備忘録と言うより愚痴に近い

カメラの接続はいたって簡単
カメラから伸びてるFFCをRasPiのコネクタに接続するだけ
ちなみにRasPiには全く同じコネクタが2つ乗っている
カメラで使うのはLANコネクタとかUSBコネクタの側にある方
向きを間違えないように接続
→確かFFCの電極がHDMIコネクタ側に来るように
後は電源を入れてraspi-configからカメラを有効にする
これだけで準備完了
撮影したい場合はraspistillコマンドを使う
最低限必須なオプションは-oでファイル名を指定する これがないと保存されない
その他コマンドは http://www.mztn.org/rpi/rpi23.html にまとまっていて見やすい

raspi-configもraspistillもSSHからできる
なのでRasPiには電源のUSBとLANコネクタを接続するだけで撮影が可能
ただ撮影した画像の確認ができないので、何らかの方法でファイルを転送する必要がある
転送にはscpコマンドが便利(ちょっと面倒だけど


で、あと色々やりたいなとおもってOpenCVを入れた
sudo apt-get install libopencv-dev
で入る(はず)
ヘッダファイルは/usr/include/opencvとか/usr/include/opencv2とかになる
なのでプログラムで読み込むヘッダファイルは<cv.h>ではなく<opencv/cv.h>とかになる
highgui.hも同様

ただ、ネットに転がってるサンプルは画面が接続されていることが前提のコードばっかりで、SSHから試すとかができない
この辺りはもうちょっと調べて見る必要がある

最近のRAMが8GBでCPUが2.5GHzで みたいなマシンばっかり使ってるのでRasPiのワンテンポ遅れたGUIはどうもストレスがたまる。。。(データがたっぷり詰まったiPhone とかも操作の反映が遅くてつらい)


やりたいこととしてはRasPi単体で動作する、画像解析装置 みたいな感じ
15fpsくらいはほしいけど、解像度はそれほど必要ないのでRasPiでも可能なはず

とりあえず今回はこんなところで
今年中にもーちょっと進めたいなぁ

2013年12月10日火曜日

映画フィルムを現像できる?

映画フィルム 劇場特典とか、初回特典についてくるアレです

どうやら現像すると捗るらしい ということでいろいろ試してみました

1.スキャナで読み込む

上はスキャナでスキャンした画像
下はフィルムの反対側から光を当ててスキャンした画像

どちらもうまく獲得できていません

上の画像の失敗した原因は
スキャナは基本的に反射した光を受光素子でデジタル化していますが
映画フィルムは透過した光を使うためです
そのために暗くなってしまいます
また、そもそもスキャナの光量では足りない というのもあります

また、下の画像ですが
僕が使っているH社のスキャナは構造的に他の光源を使うことができません
これは低コスト化のために物理的な解像度が低いのをソフトウェアで補正しているからです
(少し違いますが、まぁ似たようなもんです)
そのために外部の光源を使うと画質が悪化してしまうのです


ってことで
2.スキャナがダメならカメラ作戦
スキャナが外部光源を使えないならカメラを試すまでです
デジカメなら露出量を任意に調整できるのです

すごく…スクリーンキャプチャーっぽいです><

そもそも普通のデジカメでは解像度が圧倒的に足りません


結論:写真屋さん(photoshopじゃないよ!)に頼み込むのが簡単


映画フィルムと写真フィルムは色々と相違点がありますが、やってくれるところも有るようです

でもL版で印刷するくらいならBlu-rayを見たほうが(ry

自宅に写真現像環境が有る人とかは試してみると面白いかも?

2013年12月6日金曜日

C#で定数の配列

C#でconstを付けた配列は初期化することができません

この例の場合
constを使用したint配列のConstantList2は
"'ConstantList2' の型は 'int[]' です。文字列以外の参照型の const フィールドは null でのみ初期化できます。"
というようなエラーが発生します

しかしConstantList1はreadonlyを使っているため初期化することができます
readonlyを使用した場合、特定の条件を除き変更することはできません
そのため擬似的にconst型として使えます


readonlyは特定条件下で変更することができ、それはコンストラクタの中です
例えば上記のように宣言と同時に初期化しても、コンストラクタの中で
ConstantList1 = new int[10];
ConstantList1[0] = 10;
ConstantList1[1] = 20;
...
のようにすれば内容を変更することができます
これは一見便利なように見えますが、コンストラクタ内でreadonlyの変数を使った場合、中身を書き換える気がなくても書き換えてしまう可能性があるということです
この問題を回避する方法についてですが、一番危険な方法は「変数を書き換えないように努力する」ことでしょう
しかしそれでは意味が無いので別の方法を探す必要があります
一番簡単な方法は、例えばFunctionsというクラスがある場合、_Functionsのような関数を作り、コンストラクタFunctions内では_Functionsを呼び出すにとどめ、コンストラクタを使った初期化は_Functions関数内で行う という方法があります
この場合一手間余計に必要なのと、関数を1個呼び出すためのオーバーヘッドが必要になってしまうという問題が有ります
しかし一旦関数を呼び出して、コンストラクタの外側に出てしまえばreadonlyの変数を変更することはできないため、一応効果はあります


いくつかの利点や欠点がありますが、readonlyを使えば変数の定数配列を使うことができるので、状況によってはうまく使うと便利かもしれません

2013年12月3日火曜日

ステッピングモーター

ストロベリーリナックスで売ってるステッピングモータ

12026 12081 12082 18179
トルク 0.23N/m 0.43N/m 1.76N/m 0.48N/m
電圧 12V 2.8V 3V 3V
電流 0.33A 1.68A 3A 1.7A
電力 7.92W 9.408W 18W 10.2W
重量 0.2kg 0.34kg 1.1kg N/A

電流は1相あたりの値です
実際には2倍の電流が必要になります
電力は電圧*電流*2で2相分です

4個目のモーターの重量は調べていません
おそらく500g前後だと予想されますが、性能的に微妙なので無視しました

結局のところ一番大食いで一番重いモーターが一番トルクが有るようです

12026は電圧が12VのためL6470でも制御できます
他のモーターは電圧が低いので不明です
L6480は電圧の低いモーターにも対応できるようですが、6470は未確認です