2016年3月7日月曜日

C#のGraphicsでException

C#でBitmapを読み込んでGraphicsを作ると"インデックス付きのピクセル形式をもつイメージからグラフィックス オブジェクトを作成することはできません。"という例外が投げられる。



例外が発生したBitmapのPixelFormatを見るとFormat8bppIndexedとなっている。これは8bitのカラーパレットを使用した画像を読み込んでいるためと思われる。C#側で対応しようと思ったのだけど、画像フォーマットの変換とかは見当たらなかった。ということでとりあえず画像側で対応した。



Paint.NetでPNGを保存する際に自動検出を使うと、モノクロの画像(というか8bitパレットで対応できる画像?)は8bitで保存される。保存する際に24bitとか32bitで画像を保存してやるとGraphicsの作成が成功する。

画像のラベリングと重心

画像のラベリングを行い、ラベリングした結果の重心を表示する というモノを作ってみました。試しに鳥の写真を読み込ませてみます。



上が元画像、下が結果です。元画像は実際の写真をモノクロ化し色を逆転した画像を使用しています(元の画像は逆光で鳥が黒く抜けているため、白検出のために)。ラベリングした結果の枠を灰色で、重心を赤色で、物体の面積を緑で表示しています。

この方法で鳥を追尾する場合、鳥が羽ばたくと見かけ上の面積が変わりますから、一番大きい物体を追尾する といった単純な方法ではうまく動かないと思います。位置関係を解析したうえで、連続して一つの物体を識別する といった処理が必要かもしれません。

熱赤外線画像誘導なんかは一番大きい物体(飛行機)を追いかければ良い気もしますが、追いかけられる方は単純なフレアでは回避できなくなるので大変そうです。小さなフレアをバラまいたところでせいぜい処理時間が増える程度の妨害しかできない気がする。熱画像対策だと燃料をダンプして着火して広範囲に高温をバラ撒くとかのほうが良いのかも?


とりあえず、背景に雲とか余計な物体が無い、綺麗な環境での画像ではちゃんと物体の検出ができるので、あとは実環境向けの処理をどうするかですね。実環境でWebカメラとかをソースにして飛行機とかを検出できるようになれば、飛行機とかロケットも追尾できるかもしれません。

2016年3月6日日曜日

画像の重心





ふと思い立って画像の重心位置を計算して遊んでいる。上からブルーインパルスのT-4、空自?のUH-60、ボーイング777の写真を読ませたところ。
処理としては 1) カラー写真のモノクロ化(人間の感度に合わせてWB化) 2) 画像の二値化(任意の閾値) 3) 重心位置の計算 という感じ。また1の前に処理しやすいように512x512にリサイズを行っている。
背景ホワイトと背景ブラックがあるが、逆光気味の場合は背景ホワイトとなり、順光で撮影した場合は背景ブラックとなる。カメラの自動追尾とかを行うには背景Wと背景Bの自動検出を行う必要がありそう。もちろん輝度とか閾値も自動で調整する必要があるのでその辺りもうまくやる必要がある。

カメラの自動追尾に使う場合、T-4やUH-60は綺麗に中心を検出することができている。しかしB777は飛行機雲が明るいため、機体だけではなく、飛行機雲までを含めた重心が計算されている。ラベリングを行って一番大きな目標を捉える、といった処理を行う場合でも、飛行機雲と機体が連続しているので不可能っぽい。飛行機雲は結構モコモコしてるので、画像認識とかやるなら直線を探して、それらを追尾したほうが良いのかも。

USBカメラとかOpenCVとかを使えばリアルタイムに画像を読み込んで重心を計算する といったことができるようになるので、その結果を電動雲台に流し込んで自動追尾 とかもできるようになるかもしれない。ただし実際の環境は背景ノイズがかなり問題になりそう。雲が薄い空を飛ぶヘリコプターとかは結構認識しやすそうだけど、巡航高度の旅客機だとか、地上を移動する物体を検出するのは大変そうだ。

2016年2月27日土曜日

SDRでラジコンのバンドチェック

今時VHFかよ、って気もしますが、SDR#でラジコンのバンドチェックが可能です。
27MHz、40MHz、72MHzの周波数は同時に複数の送信機がONになるとマズイので、ちゃんとしたラジコンの飛行場とかは周波数管理もちゃんとしていますが、周りに使ってる人がいないとも限らないので、ノートPC1台あれば簡単にチェックできますよ ということで。
もっともそれぞれの周波数帯が離れすぎてるのでSDR1個あたりバンド1個しかチェックできませんが。空物の飛行場の場合はワンセグチューナを2個用意するか、1つのバンドしか許可しないみたいな運用になると思います。
田舎で自分の敷地で遊ぶ 周りにはラジコンやってる人はいないけど念のため という風にサクッとチェックすることもできます。

周波数多重で同時通信が可能なモノ(ラジコン・特小無線等)はSDRでチェックするとどこを使ってるか一発でわかるので便利ですね。




2016年2月25日木曜日

C#の文字列の指定位置を置換する

C#の文字列で一部を置換したかったのだけど、欲しい機能が無いっぽいので作ってみた。

やりたいこと
入力: "012345679", 2, "ABC"
出力: "01ABC56789"

とりあえず拡張メソッドで作った。"0123456789".Replace(2, "ABC") で"01ABC56789"が出力される(はず)。動作チェックはあんまりしてないので間違ってるかも。


public static string Replace(this string Before, int Start, string Insert)
{
    if (string.IsNullOrEmpty(Insert))
    {
        return (Before);
    }

    if (Start < 0)
    {
        Insert = Insert.Substring(-Start);
        Start = 0;
    }

    {
        int hoge = Before.Length - (Start + Insert.Length);
        if (hoge < 0)
        {
            Insert = Insert.Substring(0, Insert.Length + hoge);
        }
    }

    string s1 = Before.Substring(0, Start);
    string s2 = Before.Substring(Start + Insert.Length);

    return (s1 + Insert + s2);
}

2016年2月20日土曜日

鳳龍4号

先日のH-IIA F30でASTRO-Hが打ち上げられ、同時に3機のキューブサットも打ち上げられました。
現時点ではH-2A R/BとASTRO-Hの他に4物体の計6物体がTLEに掲載されています。
JavaS Orbit
そのうちキューブサットは3個ですが、これらについてはまだ確定していません。

さて、そのキューブサットですが、3機とも430MHz帯のビーコンがあります。ということでその辺りを受信してみました。バンドプランでは衛星の帯域は3MHzが確保されていますが、今回打ち上げられた3機は0.3MHz程の距離なので、SDRの0.900001MHzでカバーすることができます。

受信環境はワンセグチューナに市販の430MHz15エレの9エレのみを直結し、SDR#でIQを受信、受信完了後にスペクトルを可視化しCWをデコード、という手順です。今回の打ち上げでは軌道傾斜角は31度で、北海道からは好条件でも仰角10度前後までしか上がってきません。衛星との距離もかなり離れているので、固定アンテナでもアンテナの視界にいる間にかなり受信できます。自宅の窓の方向、南西に向けてインシュロックでベランダに固定したアンテナでも綺麗に受信できました。

以下の図はかろうじて鳳龍4のコールサインの一部が読み取れる状態です。


別のパスでは"JG6YBW HORYU4"と、コールサインと名称の両方を明瞭に受信できました。


一番条件が良かった時はChubSat-2のあたりにも小さなピークが見えたので、それも今後デコードしてみようと思っています。

それと、仰角がほとんど無いせいか、ベランダに設置してある市販のダイポールアンテナでもそれっぽいピークを受信することができました。今回打ち上げられた衛星は高緯度地域からはほとんど水平方向に見えますから、トラッキングする機材が無くても狙い目だと思います。

2016年2月15日月曜日

Windowsのショートカットで起動オプション

WindowsのEXEは右クリックからショートカットを作成できる。そのショートカットにはリンク先のテキストボックスに起動するEXEのパスがあり、そこにオプションを追加すれば起動オプションとして渡すことができる。

参照:クラウドサービスプラットフォーム Cosminexus:eclipse.exeの-cleanオプションをショートカットに設定する:ソフトウェア:日立

じゃぁスクリーンセーバーにも起動オプションを渡せるのか?と思って試してみた。
御存知の通り、WindowsのスクリーンセーバーはEXEの拡張子をSCRに変更したものだ(そのため中身はEXEと全く同じであり、EXEと同じ動作が可能。なのでウイルスソフトウェア等がスクリーンセーバーに擬態して入ってくることが可能)。
リンク先のEXEをコピーしてSCRに変更、同時にリンク先のファイルもEXEからSCRに変更する。そうすればそのショートカットはスクリーンセーバーになりインストールすることが可能。次にEXEと同じようにリンク先に起動オプションを追加して起動する。そうすると、起動オプションは無視され、実行したファイルパスと"/S"という文字列の2個が渡された。ということで、SCRというショートカットにオプションをつけてもWindows側で不要な文字列は削除するらしい。

さて、"/S"というオプションだが、これは「あなたはスクリーンセーバーとして起動しなさい」とEXEに知らせるためのものらしい。他にはPやCがあり、それぞれ「プレビューモードで動作しなさい」と「コンフィグモードで動作しなさい」という意味らしい(プレビューは基本的にSとして理解していいようだ)。

普段から使用できるソフトウェア(EXE)だが、起動方法によってはスクリーンセーバーとして動作し、起動オプションで設定を渡す、という動作を行いたかったが、そのような動作はできないようだ。正しい動作としては/Cで設定アイアログを表示し、適当なフォルダに設定ファイルを保存、/Sで起動された場合は設定ファイルを読み込んでスクリーンセーバーとして動作、オプションがない場合は通常のEXEとして動作する、あたりが落とし所かもしれない。