前回の下記ネタの後半、eBUSのバッファの中身を参照していました。
が、とんでもなく嘘を書いていましたので、ここで訂正させて下さい。
× 画像の先頭行ですが、 今回は8bitのカラー画像なので幅の3倍
→ PixelFormatが”BayerRG8”でしたので、幅はそのままで変わりません。
もし”RGB8”等でしたら、各画素毎にRGBが有りますので3倍になります。
それ以前にBayerって何?ってお話は、下記辺りを見て下さい、
要はMonoと同じデータ量でカラー画像を表せる仕組みです。
と言うわけで、eBUSの前にBayerの補足説明をもう少しだけ。
Bayer時の画像データ
センサー表面のカラーフィルターの色の並びをBayerパターンと呼び、
代表的なものとして、下記のようなパターンが有ります。
RGだと画像左上からR,Gの順に色が並んでいます。
カメラとしてはPixelFormatを見れば、どのパターンかが判ります。
BayerGR8 8bit GRパターン
BayerRG10 10bit RGパターン
BayerBG10p 10bit BGパターン、末尾のpはPacked (データを詰める)
Bayerの場合、各画素毎の元データはRGBいずれか一色になるので、
データ量はMonoと変わりません。(データ量減らせるのはメリット)
各画素毎に、自分に無い色は周辺の画素から計算します、
これをBayer補間、デモザイクなどと言います。
例えば下記中央の”B”画素ははBlueの色しか持っていないため、
B画素のR情報 = (R1 + R2 + R3 + R4) / 4
B画素のG情報 = (G1 + G2 + G3 + G4) / 4
というふうに、周辺画素の色を参照し、平均して使います、
これを画像全体に実施することで、画像全体のRGB画像が得られます。
上記は一番シンプルな方法で、実際はもっと複雑なやり方だとか、
各メーカーやSDKなどで、色々工夫されているようです。
余談ですが、Bayerパターンも上記以外にもっと複雑なやつとか、
IRデータが入ったパターンなども出てきているようです。
eBUSのバッファを見てみる
今回の本題、eBUSの話に戻ります、前回同様のカラーバー出力状態、
PixelFormatは”BayerRG8"に設定しています。
今回も先頭行だけ読むので、UnSafe部分を下記に変更しました。
// Operation result of buffer is OK, display. if (lOperationResult.IsOK) { // Get TimeStamp lThis.label3.Text = lBuffer.Timestamp.ToString(); // Display Image lThis.displayControl.Display(lBuffer); // Get Raw Data unsafe { lThis.sb.Clear(); byte* pArray = lBuffer.DataPointer; for (int i = 0; i < lBuffer.Image.Width; i++) { lThis.sb.Append(pArray[i].ToString()); lThis.sb.Append("\r\n"); } } }
画像の幅は1936Pixel、カラーバー8色なので一色辺りは 1936 / 8 = 242Pixel
先頭行は下記のような並びになっていると考えられます。
PixelFormatがBayerRG8なので、先頭行はR,G,R,G,R,G,R,G...の順に色が入っています、
カラーバーの切り替わる座標毎にRとGの色を調べると、こんな感じに。
更に二行目(B,G,B,G....の順)を読み、同様にBの色も入れると
当たり前ですが、カラーバー通りのRGB各色が入っていることが判りました、
実際の表示は、先ほどのBayer変換を施して全体をRGB画像としているはず。
PilxelFormatを”BayerRG10”に変えてみる
PixelFormatを”BayerRG10”に変えて、同様に先頭行を読んでみます、
この場合、1画素辺り2Byteになります、先頭12Byte(6画素分)こんな感じ。
以前のJAISDKネタで書きましたが、下記データ並びになっています。
(ややこしいですが、上図と上位下位逆で見て下さい)
先頭部分はカラーバーの白なので、8bit時はRGBとも222 でした、
上記を計算すると0x037A→ 890 で4倍になっており、
合ってそうです。(これも当たり前ですね)
PilxelFormatを”BayerRG10p”に変えてみる
PixelFormatを”BayerRG10p”に変えて、同様に先頭行を読んでみます、
この場合ちょっとややこしいです、先頭12Byteのデータ並びはこんな感じに。
5Byte=40bitで4画素分を表しています、ってこれも以前書いてましたね。
先頭行全体は (1936 / 4) * 5 = 2420 Byteになります。
先ほどのBayerRG10だと、1936*2 = 3872 Byte必要なので、
同じ10bitでも、データ量を約63%ほどに抑えることが出来ます。
例えば先頭の5Byteから得られる4画素分の各画素値は
下記のように計算出来ます。(当然ながら全て890になります)
画素1 = 122 | (( 235 & 0x03) << 8)
画素2 = (235 >> 2) | ((173 & 0x0F) << 6)
画素3 = (173 >> 4) | ((183 & 0x3F) << 4)
画素4 = (183 >> 6) | (222 << 2)
まとめ
eBUS SDKでは、lBuffer.DataPointerでバッファの先頭アドレスを取得出来る、
UnSafeコードでJAISDKと同様にバッファを参照出来ることも判りました。
Packedの場合、データの取り扱い(並べ替え)が少し面倒臭いです、
eBUS SDK側で並び替えて出してくれる方法が有るのか? 調べてみます、
うまく行けば次回のネタですね、今回はここまで。