区画線認識論文サーベイ

区画線認識技術は自動運転、HDMap(High Definition Map)構築などの領域で必要不可欠になっています。このブログは区画線認識に関する基本知識や最近の論文について、書いていきたいと思います。　アジェンダーとしては、まず区画線の問題設定、次に処理の流れ、データセット、評価指標、最後に論文紹介、と言う順番に進めてきます。

# 問題設定
### 導入
まず、区画線と言うのは道路の構造の保全と交通の流れを誘導するために設置される路面標識の一種です。 路面にある区画線の位置や種類、色などの情報を検出するのは区画線認識の目標です。　下記の図のケースでは、　シーンが高速道路で、　検出対象が走行している車道の区画線だけ、しかも前方のかなり近いところまでしか検出していない。　このような問題設定では、すごくシンプルな手法でも大体90%のケースはカバーできます。
[1] <img width="1400" alt="0_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/196599fc-016c-c8bc-e957-a36c7038740c.png">　

### 応用先
区画線検出と言うモジュールをどこに使うかによって、要求される精度、信頼度、そして問題のスコープが変わります。下の表では、 featureとdescription(どう言うタスクで使うか)、lane/road understanding demands(どう言う要求を満たすべきか)といった情報がまとめられています。　表の下に行くほど、タスクが複雑になって、要求も厳しくなることが分かります。　例えば、一番簡単なLDW（車が今走行している車道から離れそうになったら、警告を出す）と言うタスクでは、二本の区画線を検出できればよくて、しかも前方からかなり近い距離までできればいい。　一方、Turn Assit(車道変更の補助)と言うちょっと難しいタスクになってくると、走行している車道だけではなく、他の車道の区画線も検出する必要が出てきて、さらに車道変更判断のための情報も必要になります。
[2] <img width="1073" alt="0_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/9aede400-2fff-6bb8-b6b5-236628d28d96.png">

### 実世界の状況が複雑
また、現実世界では、区画線認識をさらに難しいタスクにしている様々の要因があります。
<img width="288" alt="0_3_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/d48c8b84-a6a3-3e92-beb3-f4e9f3d995ef.png">　(区画線の多種多様な見た目)[2]
<img width="282" alt="0_3_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/ad97151e-d227-b251-dca4-dfc4b9224c51.png">　(前方車両などによる遮蔽 )[2]
<img width="286" alt="0_3_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/9772db59-f6e7-ded5-c1ce-ce5629d32318.png"> (気象状況や光の反射による視界状況の悪化) [2]

### 区画線検出で使う情報
どう言うデータを使って、区画線を検出するのか、と言うと、一番よく使われているのは**映像**です。直感的に、人間は目で見て、区画線の認識をしているので、それを機械にやらせるには、映像データが必要不可欠です。 次は**LiDAR**です。LiDARとは、光を発射して、光が対象物にぶつけって帰ってくる時間を測ることで、対象物との距離や位置を計測する装置です。LiDARが映像データより優れているのはより正確に3次元情報を取得できるところです。また、**GPS/IMU**は区画線の絶対の座標値を知るために、必要な計測装置です。

# 区画線検出の処理の流れ
処理のパイプラインに関して下記の図は一般的な処理流れです。
[2]<img width="860" alt="0_5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/74aa28aa-bca0-dca4-da2e-af4acbc24e63.png">
これはdeep learningが流行る前に、伝統的なコンピュタービジョン手法を使うことを想定している流れなので、deep learningを使えば、上記のステップが一部不要になった理、他のステップとマージできたりします。
1. **image cleaning**: つまり前処理です。区画線検出にとって、邪魔となるようなものをあらかじめ除去すると言う処理です。例えば、前方の遮蔽の車とか、路面に落とされている影とか。
2. **feature extraction**: 画像から区画線っぽい領域の座標やfeatureを抽出するステップです。
3. **model fitting**: 前のステップで抽出した区画線っぽい領域を曲線なり、なんなりでフィッティングする
4. **time integration**: 運転の映像データを扱う場合、今までのステップは映像の各フレームを独立に扱っていました。time integrationと言うのは時刻tのフレームの区画線を検出するときに、時刻t-1,t-2などのフレームの検出結果との整合性を見ながら、やると言う感じです。
5. **image to world correspondence**: ここまでのステップは同じ２次元の画像内の話ですが、ここでは、各フレームで検出した結果を３次元空間に射影するなどの処理がされています。

# 評価指標
区画線検出の評価指標ですが、　区画線認識を一つのモジュールとしてシステムに組み込む場合、このシステムの目標によって、評価指標が変わります。　区画線検出と言う部分に限っていうと、**区画線ベース**と **ピクセルベース**、この二種類の評価指標がよく使われています。
ピクセルベース：　モデルが予測した区画線のピクセルとアノテーションのピクセルとのIoU(Intersection over Union)を見ています。つまり、真値との重なり度合いを重点に置いています。　一方で区画線ベースはモデルが予測した区画線ピクセルからフィッティングした曲線と真値の曲線の距離を見ています。つまり、真値との近さを見ています。本質的にはあまり違いがないように見えますが、算出方法は違うので、注意を払った方がいいです。
ピクセルベース
<img width="782" alt="0_6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/d34b1625-16d8-2d23-e441-7c042b45aa60.png">
区画線ベース
<img width="831" alt="0_7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/a7bd381c-23f1-4c27-e4d9-3f2c5dcd8f5b.png">

# データセット
区画線認識に関して、公開されているデータセットは主に二つあります。下記の表にまとめました。


| データセット      |  画像枚数(Train/Test)  |  画像サイズ | データ取得エリア | 
|:--------------------:|:----------------------:|:------------------:|:------:|
| Tusimple Lane Marking Challenge [3]  | 3626/2728  | 1280*720 |高速道路（アメリカ）|
| CULane [4]                           | 88880/34680 | 1640*590       |北京市内|

# 論文紹介
### 1 Spatial As Deep: Spatial CNN for Traffic Scene Understanding (AAAI2018)[4]
　この論文はspatial cnnという独自で提案したレイアを既存のsemantic segmentationのネットワークに差し込むことで、モデルの精度を高める、ということを主張しています。　
　学習のフェーズは下記の図の(a)に示されています。　まずは画像をbackboneに通してfeature mapを生成します。次に、ネットワークが二つのブランチに分かれて、右の方はこの画像に区画線何本あるのか、をそれぞれ予測します。１はある、０はなし、という風になっています。ここに四つの数字が出てくるのは最大4本の区画線しか検出出来ないということです。左のブランチは区画線のfeatue mapで、サイズがW*H*5です。５チャンネルの内訳は4本の区画線とbackgroundのコンフィデンススコアです。
　推論時は図(b)にあります。画像がモデルに入ってきたら、右のブランチの出力を見ます。スコアが高い区画線、ここでは2本目と3本目と４本目、これらの位置座標を左のfeatue mapより出力する、という流れです。
<img width="666" alt="2.1_scnn_architecture.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/2900d0d0-bfce-f3e8-93c7-ba175aa76bcf.png">
　次はこの論文の一番重要なところspatial cnnです。　この真ん中の部分はSCNNのモジュールに当たります。簡単にいうと、一つのfeature mapをもらって、何かしらの演算を行なってまたfeature mapを出力する、というようなレイアです。　通常の畳み込みレイアでは、このレイアの値は一層前のレイアの値によって算出されますが、このspatial cnnは自分自身の値を使って、自分自身の値を更新するというようなレイアです。　このレイアは四つの部分からなりますが、まず上から下まで計算を行う部分を見ていくと、入力のC*W*Hのfeature mapをH個のW*Cのfeature mapと見なすことができます。例えばこの２番目のfeature mapを見ると、このFMの値はイコール自分自分の値プラス一つ上のFMの一定の領域の値の重み付き総和。３番目のfeature mapの値は同じ仕組みで更新されます。ただし、３番目のfeature mapを更新するときに使われるのは更新した後の２番目のfeature mapの値です。こうやって最後のfeature mapまで値の更新を繰り返していきます。 同じやり方で、下から上まで、奥から手前まで、手前から奥まで、合わせて４回、計算します。
<img width="661" alt="2.2_scnn_module.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/1097774b-5a5d-9e5d-5709-9bf630cedb84.png">
　この論文の評価指標ですが、区画線に30pixel分の幅をもたせて、モデルの予測とground truthのIoUを図って、precision ,recall,及びF scoreを評価指標にします。下記の表はCULaneのデータセットにおける結果ですが、baselineというのはdeeplab_v1で、extraConvというのはパラメーター数を切り分けるために、入れた普通の畳み込みレイアです。 この表を見れば、SCNNの有効性はわかると思います。 
　　<img width="442" alt="2.5_scnn_exp1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/9989183d-3896-fe5c-ff3d-7868c0bdbd1d.png">

### 2 Towards End-to-end Lane Detection: an Instance Segmentation Approach　[5]
  この論文の提案手法はinstance segmentationseベースの手法で、モデルは区画線のピクセルをを出すsemantic segmentationブランチとピクセルを区画線ごとにクラスタリングするのに使われるembeddingベクトルを出力するブランチ、この二つに分かれます。下記の図を参照。 
　<img width="902" alt="3.1_fs_architecture.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/10da8c9d-2d41-0e12-8b4d-11b6d63deba9.png">
　semantic segmentationのブランチは普通に区画線の領域のアノテーションがあれば、学習はできますが、 クラスタリングのためにembedding ブランチはどうやって学習するのかというと、下記の図では、各点は一つのピクセルのembedding ベクトルで、同じ色の点は一つの区画線のピクセルを意味します。つまり、この図では、区画線3本ある、という感じです。 まずは、同じ区画線に属する点は一つのグループとみなして、このグループの各点のベクトルは、このグループの全ての点の中心点にできるだけ近づけるように、ベクトルを学習します。 これはつまり1行目の式の目的です。 Ucはグループcの中心点、xiはこのグループの中の一つの点、vは閾値です。 次は別のグループの中心点ができるだけ離れるように、ベクトルを学習します。 図で言うと、青いバツの点と赤いバツの点と緑のバツの点を遠ざけるようにモデルを学習している、というような感じです。
　<img width="446" alt="3.2_fs_embedding.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/2136b624-dce2-a200-5b07-2915f5980d53.png">

### 3 LaneNet: Real-time Lane Detection Networks for Autonomous Driving [6]
   この論文の処理の流れはまず、区画線っぽいピクセルをsemantic segmentationで出してから、 次にピクセルから区画線を検出する、と言うような流れです。 下記の図は区画線っぽいピクセルを出すところのlane edge proposal networkに当たります。 入力は普通の画像ではなく、bird-sight 変換後の画像です。 Bird-sightと言うのは真上と言う角度から見た画像のことです。
　　<img width="507" alt="4.1_lane_line_proposal.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/ee559faf-a04c-ed06-4b3b-9fc1de658f36.png">
　　次ははピクセルから区画線を出す部分です。 この部分の入力は区画線ピクセルの座標になります。 例えばLane edge proposal networkからn個の区画線ピクセルが検出できたら、各ピクセルのx、y座標を一列に並べて、長さが2*nのベクトルにして、localization networkに入力します。ピクセルの座標の並べ順が結果に影響しないように、畳み込み層のカーネルサイズを１にして、さらにチャンネル方向にmax poolingも入れています。 こう言うレイアをいくつか重ねて、最後にLSTM層に入れます。 各ステップの出力は一本の区画線と一つのスコアで、このスコアは出力をいつ止めるかをコントロールしています。
　　<img width="667" alt="4.2_lane_line_localization.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/1b334b51-704e-2312-4695-40420e1d2052.png">
　　検出結果は下記の図になります。
　　<img width="919" alt="4.2_result.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/306a8e2e-aea9-69e8-2299-8887d5bda333.png">

### 4 EL-GAN: Embedding Loss Driven Generative Adversarial Networks for Lane Detection. [7]
  この論文は区画線のピクセルを出しているsemantic segmentationの部分をGANで高精度化する論文です。 
　まずはGeneratorの部分です。 Generatorを学習するロスは二つの部分に分かれます。 一つ目はgeneratorが出した区画線のbinary mapと真値のbinary mapとのpixel-wiseの cross entropyです。これは普通のsemantic segmentationを学習した時と同じロスです。 二つ目はGAN特有のロスです。Generatorが出力したbinary mapをdiscriminatorが真値に思わせるように、generatorを学習する。 ってことはgeneratorの出力をdiscriminatorに入れて、真値のラベルを出力させるのですが、これだと、学習は安定化しないと言う欠点があるので、ganの分野でperceptual loss見たいな考え方で、 真値のラベルをDに入れた後に、ネットワークの後半のレイアのfeatureと予測の binary mapをDに入れた後に、ネットワークの後半のレイアのfeature, この二つのfeatureのL2ロスを取っている。
　次の部分はDです。 これは通常のGANのDの学習と同じです。つまり、真値のラベルを真値に、gが生成したものを生成したものに分類できるように、モデルを学習すると言うことです。
　<img width="631" alt="5.1_gan_architecture.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/95b0946b-47c4-0545-6e1b-a692bca59090.png">
　検出結果ですが、下記の図を見ると、入力データは１列目で、これに対して、ganを使ったモデルの出力と通常のsemantic segmentationの出力を並べたものです。GANの方がノイズが少ないことが分かります。
　<img width="726" alt="5.2_gan_result.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/7c79fdd3-61e4-fa1d-df54-015b4d9cf3e9.png">

### 5 FastDraw: Addressing the Long Tail of Lane Detection by adapting a sequential Prediction Network

この論文の面白いところは、出力ヘッドの部分です。 一般のやり方では、出力の部分は区画線のbinary mapで。 Binary mapの各グリードの値はそのグリードが区画線の確率です。なので、 binary mapは縦長*横幅の二次元テンソルです。チャンネル数が１。 この論文では、最終出力のチャンネル数が1ではないです。ってことはbinaryではなくなります。具体的には、あるピクセルが自分が区画線である確率だけではなく、周辺のピクセルの確率まで出している。 例えば、下記の図では、一つの黒い点はfeature mapの一つのグリードだと思ってください。(b)を見ると、まずb自身の確率を出します。次に、1行上のピクセル、流石にこの行の全てのピクセルみるわけにはいかないので、真上の左からL個のピクセルと右からL個のピクセル、と真上のピクセル、合わせて、2L+1個の値を出力しています。また、この2L+1の中に区画線ピクセルが一個もない場合の確率も出しています。つまり自分の先には区画線ピクセルがありません、ということです。これで全部2L+2の値になります。 先ほどは上から見たときの話ですが、下方向も同様にやります。 このやり方のメリットは後処理をする必要がなく、区画線上の一つのピクセルでも分かれば、芋づる式に全部のピクセル出せるところです。
<img width="338" alt="7_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/9189fe65-61ea-ef6d-f761-0a30ff9acefb.png">

ネットワークの出力のヘッド部分の図は下記のようになります。
<img width="1001" alt="7_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/33b8150a-802e-a76a-b754-c375c1a293e8.png">

可視化の結果ですが、左から１列目は入力画像、２列目は1行上のピクセルの確率の可視化図、３列目は一行下のピクセルの確率の可視化図、４列目は普通のbinary mapの図、５列目はbinary mapを元画像にプロットした結果になります。
<img width="508" alt="7-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/739c6b06-9a7a-d5ca-f116-c05d3fa1fb27.png">

### 6 Learning Lightweight Lane Detection CNN by Self Attention Distillation.
 Attention distillationを使うことで、区画線を検出する、というような論文です。 普通のdistillationというのは、精度が高い教師モデルが精度が低い生徒モデルに情報を教える、つまりネットワーク二つある、というイメージですが、 この論文では、ネットワーク一個しかなくて、つまり、自分が自分自身に情報を教えるということです。具体的には、出力に近い層が入力に近い層に情報を教える。情報はattentionという形になっています。 
 下記の図では、上はattentionを適応する前、下は適応した後の結果で、青い図はネットワークの各ブロックのfeatureから算出したattentionマップです。 学習エポック40k, 50k, 60kのattention mapを見ると、見た目はそんなに劇的に変わっていない。 しかし、40k目エポックからSADを導入すると、ぼやけていた右の二本の区画線もちゃんと出るようになった、ということが分かります。
<img width="717" alt="6.1_result.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/2388a26c-c4ff-539c-6a27-5dae8c81148c.png">

Attentionマップはどうやって作るのか、 簡単にいうと、チャンネル*縦長*横幅の三次元畳み込みfeature mapを縦長*横幅の二次元feature mapに変換する。というようなことをやっています。各グリードにチャンネル方向で値をマージする必要がありますが、著者が色々試した結果、これらの値を二乗して、足し合わせた方が精度がいいことが分かりました。 　
<img width="442" alt="6.2_attention_map.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/8c2c0f7c-cfd0-387d-9a62-2636dfa075ff.png">

では、どうやって、distillationを行うのかと言うと、まずは各ボロックごとに、attention mapを作ります。次に、各attentionマップが次のブロックのattentionマップに近づくるように、学習が行われています。
<img width="714" alt="6.4_architecture.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/a7c3c5ee-fefa-dd28-acb8-bf8b09d9aad9.png">

実験結果についてですが、下記の図はTusimpleにおける結果です。提案手法の方が一番精度がいいことが分かります。
<img width="447" alt="6_6_experiment.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273462/9f6917a0-41bc-d013-849f-28aedce05d2a.png">

# まとめ
この記事は区画線認識に関する基本知識や最近の論文についてに関して、まとめました。ネットに他にも参考になる資料がたくさんあります。例えば、https://github.com/amusi/awesome-lane-detection に区画線に関する論文のリンク集があります。　また、実際手を動かしてみたい場合、[4][5][9]の論文はコードが公開されているので、試してみるといいでしょう。


# Reference
[1] https://www.youtube.com/watch?v=WsWCAi7tkv8
[2] Recent Progress in Road and Lane Detection - A survey 
[3] https://github.com/TuSimple/tusimple-benchmark
[4] Spatial As Deep: Spatial CNN for Traffic Scene Understanding (AAAI2018)
[5] Towards End-to-end Lane Detection: an Instance Segmentation Approach
[6] LaneNet: Real-time Lane Detection Networks for Autonomous Driving
[7] EL-GAN: Embedding Loss Driven Generative Adversarial Networks for Lane Detection.
[8] FastDraw: Addressing the Long Tail of Lane Detection by Adapting a Sequential Prediction Network (CVPR2019)
[9] Learning Lightweight Lane Detection CNN by Self Attention Distillation (ICCV2019)