はじめに
ここでは SH2の中の、SH7144Fを搭載したマイコンボード (インターフェイス誌2006.6号付録) と浅草ギ研製CMOSイメージセンサーボードCMOS-EYEを使って、撮影したグレー諧調画像を白(255)か黒(0)の2つの値に変換する処理を紹介します。これは、文字認識や形状認識の際に、8ビットのグレー画像を「画素がある(黒)かない(白)か」の画像に変換することで処理を簡単にする前処理としてよく使われます。
尚、このページは「SH2...バス接続及びシリアル接続」のページので作成した環境を使用しています。ハード接続、画像へのアクセス方法、アドレッシングについては事前にこちらを参照願います。
※このページで紹介する内容はあくまでも一例です。個別の作成のご相談ご質問はお答えできませんのでご了承下さい。このページと同じ内容についてのご質問についてはロボット掲示板にてお願いいたします。
用語について
このページで説明する用語について解説します。
CMOS-EYEはマイコンと接続することが前提となっております。以下の説明で「マイコン」と書いたところは、CMOS-EYEに接続するユーザー側のマイコンを示します。マイコン側の端子名は極力、そのマイコンのデータシートに書かれている名前を記載しています。
マイコンチップが載ったCPUボードを「マイコンボード」とします。マイコンボードの端子名は極力、そのマイコンボードの取扱説明に書かれている名称を記載しています。
CMOS-EYE上にも制御用のマイコンが搭載されていますが、これは「CMOS-EYE上のマイコン」とします。(バス接続時には特にこの「CMOS-EYE上のマイコン」を意識する必要はありません。)
CMOS-EYEからはいろいろな端子が出ています。アドレスを指定する端子の集まりを「アドレスバス」とします。又、データを指定したり受けたりする端子の集まりを「データバス」とします。
ニ値化処理について
たとえば、白黒画像を撮影し、文字や物体の形状を判定したいとします。
例として、このような画像を撮影し、線が書いてある部分だけを抽出しようと考えます。
80x60画面を拡大したもの。
この場合、濃度データは8ビットで表されますので、各ピクセルのデータは0〜255の値になりますが、処理したいのは「線があるかないか」ということなので、この画像を「あるかないか」の画像に変換すると後の処理が楽になります。
CMOS-EYEの白黒画像の値は、黒いほど0になり、白いほど255になります。
<固定しきいニ値化値処理>
よって、あるしきい値を決めて、単純に元画像をその値以上か未満かを判定し、黒(0)か白(255)で画面を書き直せばニ値の画像が得られます。
ちなみに、ニ値はどのような値でも良いのですが、Viewerで表示したときにわかりやすいように、極端な値、0か255とします。また、「対象がある」部分を0としておいた方が、後で対象物に番号付けをする(ラベリングという)のに都合が良いです。0,1,2,3と番号付けするのは自然で、Viewerで見ても見えますが、255を基準にして254,253,252,251と番号付けするのは不自然で、Viewerで見ると白に近くて見えません。
<可変しきいニ値化処理>
しかし、ある1つの値をしきい値として上下を判定する場合は少し問題が起きる場合があります。それは、背景が単一色でない場合です。上の写真の例は、白い紙にマルバツを書いたものですが、紙の凹凸や光の下限で背景が暗い部分が生じています。しきい値を1つに固定すると、背景の陰影に対応できずに暗い部分も対象と判定する可能性が高くなります。このような場合は、しきい値にあるていどの幅を持たせておいて、前回の画素が対象でなかったら次もなるべく対象でないようなしきい値、前回の画素が対象だったら次もなるべく対象になるしきい値、というロジックにすると背景の陰影の問題が緩和されます。この方法を可変しきい値処理と言います。
<CMOS-EYEでの実際の処理>
ここでは、可変しきい値処理のサンプルプログラムを紹介します。しかし、CMOS-EYEではAWB機能(オートホワイトバランス)が働いているので、実際に処理結果を検討してみると可変しきい値でも固定しきい値処理でもあまりかわらない結果となっています。実際には「しきい値の可変」よりも、「どの値をしきい値にするか」という方が処理結果の変化が大きくなります。速度を上げたい場合はしきい値の可変ロジックを外すと良いでしょう。
ソースプログラムと全体の説明
CMOS-EYE_SH2_towValue.c (右クリックで保存)
ピンアサイン、ヘッダファイル、アドレスセット関数、IO初期化関数、ウェイト関数、1ピクセル読み込み関数、1ピクセル書き込み関数は以前のページ(上の「はじめに」を参照)を参照してください。
今回はニ値化処理なので、元画像は白黒になります。画面サイズは80x60で行います。よってモード設定は行302〜305のようになります。
321行は指定したアドレスの画面に対して、しきい値と幅を設定してニ値化画像を作成する関数です。引数は
元画像アドレス,ニ値化画像格納アドレス,画面サイズ,しきい値,幅
の順になります。
可変しきい値ニ値化処理のプログラム
しきい値の判定は twoValue( ) という関数にしました。下がその部分です。
前回までと同様に、SRAMにアクセスする前にCEをLOWにするのを忘れないようにしましょう。また、処理が終わったらCEをHIGHにしないと次の撮影ができない(CMOS-EYEが内部でSRAMにアクセスできないので)ので注意して下さい。
行250〜253ではしきい値の上限値と下限値をセットしています。0以下や255以上にならないように値をまるめています。
変数dataは、実際に書き込む白黒データを表すとともに、前回の処理結果をも表しています。行238では処理前の結果を背景の白(255)として、対象が検知されてない状態からスタートさせます。尚、このdataはニ値を入れるので0か255かの値しかとりません。
行257から画面の各ピクセルを1つづつ判定するので1画面分のループ処理をします。
行258と行266でデータバスを切り替えてます。データ読み出し前や、結果書き込み前にデータバスがきちんと設定されているか注意しましょう。私もプログラミング時によくこの方向設定を忘れてハマることがあります。。。
行259で前回の処理がどうだったかを判定します。もし、dataが0だったら前回黒(0)を結果として書き込んだことになり、前回は対象があったということになりますので、次の260でしきい値+許容値で計算をします。この辺りのロジックですが、対象が合った場合−>黒=0となります。ハイローと白黒と許容値プラスマイナスが逆のイメージになりますので、気をつけてください。(上の通りのロジックで大丈夫です。興味のある方は判定式を逆にしたりして結果を確認してみてください。)
行262からはその逆の処理になります。しきい値はしきい値−許容値となります。
行266と267で結果を別なアドレスに格納します。
行269と270は後処理です。これを忘れると、この関数以外のプログラムが動かなくなったり、この次の撮影が出来なくなったりしますので注意して下さい。
画像処理結果
実際に、ソースプログラムを動かしたものを、CMOS−EYE Viewerで見てみます。
撮影画像(0番地から格納)
二値化画像(4800番地から描画されたもの)
これは、しきい値=80、許容値=5で計算したものです。
しきい値計算部分の時間を測定してみました。
20mSというところでしょうか。H8Tinyだと240mS、内蔵プログラムは固定しきい値処理しかありませんが、この場合は70mSほどですので、SH2でバス接続の方が断然速いです。
しきい値と許容値を変えてみる
<しきい値=90 許容値=5>
<しきい値=90 許容値=20>
<しきい値=130 許容値=5>
CMOS−EYEですが、センサは起動時には「オートホワイトバランスがON」になっていますので、画面の平均濃度はなるべく中心値になるように撮影されます。よって、真っ白でも灰色になります。ということで、しきい値は中間濃度(値127近辺)ではなく、それよりも0に近い方に設定した方が、うまく黒を抽出できます。
許容値による変化は上の感じではあまり現れません。それよりも、許容値を大きくしすぎると、意図した濃度以外のところも拾ってしまう結果となります。
おわりに
今回は線画像を例にとりましたが、白黒で濃度差がはっきりしているものであれが、このようにニ値化画像を抽出できます。ニ値化画像はその後の認識処理の基本なのでこの例を参考にして下さい。
次はこのニ値画像を使って、線図形の処理をやってみようと思います。
2006年8月29日
|
|
|