交通標識の認識に必要な赤の検出
交通標識に使われている「赤」は、国際的に統一されていて、純粋に近い赤が用いられます。しかし、天候、陰影、逆光などによる明るさの変動(部分的を含む)、車のライトやその他の光源による、反射光のスペクトラムの変動が大きい問題があります。さらに、リアルタイム処理のための高速演算と、安全のための確実性が要求されます。
赤の検出方法のいろいろ
参考資料によれば、下記の方法が知られています。
1.RGBをHSV(HSBやHSIなどとも呼ばれる)に変換して、hue(色相)、saturation(彩度)、value(明度、brightnessやintensityとも呼ばれる)を使う方法
赤はhueが0(注1)であり、hueは明るさに影響されません。ただし、わずかに赤色をしたグレイを赤と判定してしまうのを防止するためにsaturationが低い場合を除外したり、暗部に多いノイズを除去するためにvalueが低い場合を除外したりします。RGBからHSVに変換するのにやや時間が掛かる欠点があります。
hue<0.05またはhue>0.95(-0.05<hue<0.05と同じ)であり、かつsaturation>0.5とvalue>0.01を赤と判定する例が、『Vision-Based Stop Sign Detection and Recognition System for Intelligent Vehicle』にあります。
2.RGB成分の比率を使う方法
R/GとR/Bの比率が同時に一定以上の値になる場合を赤と判定します。
参考資料には、筆者のウエブサイトの『Visual c++ 6.0を用いた易しい画像処理(14)-原画像から赤色を抽出し、一旦拡張して縮小する-』や『Road Traffic Sign Detection and Classification』があります。
3.規準化したR成分を使う方法
R/(R+G+B)のように、明るさで規準化した値を使用します。明るさの変動には強いのですが、R/(G+B)の比率を使うのと等価であり、Gの強さをBの弱さで補うことができ、抽出精度が低い欠点があります。
参考資料は、『Fast and Robust Traffic Sign Detection 』です。
4.RGB成分の差を使う方法
R>77、R-G>17、R-B>17のすべてを満足したときに、赤と判定する例が『Efficient Recognition of Speed Limit Signal』にあります。しかし、これはRGBの値の差を使うので、赤味がかった明るい白を抽出してしまったり、暗い赤を抽出できなかったりする欠点があります。
赤の検出方法の目視による比較
(1)順光下における明るいサンプル、(2)順光下で陰影のあるサンプル、(3)逆光下における暗いサンプル、(4)紛らわしい周囲環境でのサンプル、(5)夜間のヘッドライト照明によるサンプルを使用して、後述するプログラム上で抽出条件を変更しながら目視で比較した結果、次のような結論を得ました。
- HSVを使用する方法は、原理的にも分かりやすく、精度の高い抽出が可能ですが、RGBからHSVへの変換に若干時間が掛かります。リアルタイムでの検出が必要な交通標識の認識には欠点と思われます。
- RGB成分の比率を用いる方法は、簡単な手法の割には、HSVを用いるのに近い抽出精度が得られます。ただし、夜間のヘッドライトの反射による場合のように、全体が明るくなり過ぎて十分な比率が取れなくなった場合(彩度が低下する)には抽出できなくなる欠点があります。
- 規準化したR成分を使う方法は、赤の抽出精度が低い(ノイズが増える)欠点があります。
- RGB成分の差を用いる方法は、暗い赤を検出することが不可能で、実用的でありません。
以上の結果から、夜間に使用する場合の欠点はあるものの、RGB成分の比率を用いる方法が最適と判断しました。
赤の抽出方法のHSVダイヤグラムによる確認
赤の検出方法の候補(RGB成分の差を用いる方法は除外)をさらに検討するために、Testと称する簡単なアプレット(本稿に添付してあります)を作成して、図1に示す図を得ました。
![図1 「赤」として抽出する範囲をHSVダイアグラム上で比較 図1 「赤」として抽出する範囲をHSVダイアグラム上で比較](http://cz-cdn.shoeisha.jp/static/images/article/352/figure1.jpg)
図1は、横軸にhue(色相)を、縦軸にsaturation(彩度)をとったものを上段に、同様に縦軸にvalue(明度)をとったものを下段に並べてあります。左から、HSVを用いる方法、RGB成分の比率を用いる方法、規準化したRを用いる方法です。
実際にアプレットを実行してみると分かりますが、hue、saturation、valueから成る三次元のデータを二次元で表示するための無理があります。例えば、valueが異なる暗い色と明るい色とが、共に同じhueとsaturationを持つ場合があります。その場合は、後から描画する明るい色によって前の暗い色が上書きされてしまいます。従って、上段のhue-saturation図では、相対的にvalueの高い色が示されていて、下段のhue-value図では、saturationの低い色が示されています。
図1から、以下の結論が得られます。
- HSVを用いる方法は、精度良くhueやsaturationなどの範囲を決めることができます。しかし、hueが0から離れていて、saturationが比較的低い対象物は、交通標識以外である確率が高くなり、誤抽出につながる恐れがあります。
- 比率を用いる方法は、saturationの高い色に対してはhueの許容範囲が広く、saturationが低いとhueの範囲が狭くなっていて、交通標識の抽出には好都合と言えます。
- 規準化したR成分を使う方法は、予想通り、hueの範囲が広すぎます。hueの範囲を狭めようとすると、saturationの下限が高くなる欠点があります。
結局、R/GとR/Bの比率を用いる方法が最善であることが確認されました。
以上の確認に使用したプログラムの主要部分を以下に示します。このプログラムは、実行可能なアプレットTestとして添付してあります。
for(int r=0;r<256;r+=2) for(int g=0;g<r;g+=2) for(int b=0;b<r;b+=2){ //HSVへの変換 Color.RGBtoHSB(r,g,b,hsbvals); hue=hsbvals[0]; //0を中心にhueを正負で表す if(hue>0.5f) hue=hue-1.0f; sat=hsbvals[1]; val=hsbvals[2]; gr.setColor(new Color(r,g,b)); y0=Y[0]+200-(int)(200*sat); y1=Y[1]+199-(int)(200*val); x=(int)(500*hue); //HSVによる赤の検出の一例 if(hue>-0.07 && hue<0.07 && sat>0.5 && val>0.1){ gr.drawRect(X[0]+x,y0,2,2); gr.drawRect(X[0]+x,y1,2,2); } //比率による赤の検出の一例 if(r>1.75*g && r>1.75*b && r>32){ gr.drawRect(X[1]+x,y0,2,2); gr.drawRect(X[1]+x,y1,2,2); } //規準化による赤の検出の一例 if(r>0.55*(r+g+b) && r>32){ gr.drawRect(X[2]+x,y0,2,2); gr.drawRect(X[2]+x,y1,2,2); } }