opencvで特徴"線"(line_features)を抽出してみた。

# 背景
[OpenCVで油絵エフェクトは1行でかけるとのことです。(C++限定)](https://qiita.com/satsukiya/items/8adc069772df7465bd85)と同様に
[Tutorials for contrib modules(opencv-contrib-python)](https://docs.opencv.org/master/d3/d81/tutorial_contrib_root.html)で最近作成されたモジュールで割とすぐに確認できそうなのを見つけて実装しようと思っています。
今回は
##### 特徴"線"抽出
です。

特徴点 を検出する手法は `AKAZE` `BRISK` `KAZE` `ORB` `SIFT` `SURF` といろいろあるのですが線を検出する手法はあまりないはずです。

# 開発。。。したけど
[Line Features Tutorial](https://docs.opencv.org/master/df/dfa/tutorial_line_descriptor_main.html) にあるコードを元に実装しようとしたのですが、

```c++
cv::Ptr<cv::line_descriptor::LSDDetector> bd = cv::line_descriptor::LSDDetector::createLSDDetector();
```

で下記のエラーになりました。

```
Implementation has been removed due original code license issues in function 'LineSegmentDetectorImpl'
関数'LineSegmentDetectorImpl'内にあるオリジナルコードはライセンス問題が潜んでるため実装を削除したっす。
```

[OpenCVからLineSegmentDetector(LSD)が消えた](https://www.kouken-party.info/2019/05/17/opencv%E3%81%8B%E3%82%89linesegmentdetectorlsd%E3%81%8C%E6%B6%88%E3%81%88%E3%81%9F/) や [license problem in descriptor.hpp](https://github.com/opencv/opencv_contrib/issues/2016)を見るとライセンスの問題で4系から特徴線を抽出するモジュールが削除されたみたいです。


# 開発(代替)

調べると`createLSDDetector`の代わりに`createFastLineDetector`が使えるみたいです。ですが、画像を比較するメソッドはないです。なぜなら`detect`メソッドでDescriptorMatcher用の出力パラメータがないためです。`LSDDetector`のライセンスが以降フリーになるか、`FastLineDetector`専用の比較メソッドが出てくるまで待つか、各自で最近傍探索あたりを使って作成するしかなさそうです。:weary:
([Descriptor Matchers](https://docs.opencv.org/master/d8/d9b/group__features2d__match.html) を何かしらで使うのかな:thinking: )

サンプル画像はまたインスタからランダムに選びました:crystal_ball:
https://www.instagram.com/p/B34P7TeBtSk/

元画像っす
<img width="478" alt="eiffeltower.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/a24153e3-91e9-2ee3-1949-af722dd04b70.png">

使うライブラリは次の通りです。

```
 -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_ximgproc
```


```cpp
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/ximgproc/fast_line_detector.hpp>

int main( int argc, char** argv )
{
	//白黒画像(判定用)
	cv::Mat imageMat = cv::imread("./eiffeltower.png", cv::IMREAD_GRAYSCALE );
	//カラー画像(表示用)
	cv::Mat imageMat_color = cv::imread("./eiffeltower.png", cv::IMREAD_COLOR  );
	std::vector<cv::Vec4f> lines;

        //特徴線クラスオブジェクトを作成
	cv::Ptr<cv::ximgproc::FastLineDetector> fld =  cv::ximgproc::createFastLineDetector();

        //特徴線検索
	fld->detect( imageMat, lines);

	for (int i = 0; i < lines.size(); ++i) {
		//線の始点
		cv::Point pt1 = cv::Point2f( lines[i][0], lines[i][1] );
		//線の終点
		cv::Point pt2 = cv::Point2f( lines[i][2], lines[i][3] );
		cv::line( imageMat_color, pt1, pt2, cv::Scalar( 0, 0, 255 ), 2);
	}

	cv::namedWindow("line features", cv::WINDOW_AUTOSIZE);
	cv::imshow("line features", imageMat_color);

	cv::waitKey(0);

	cv::destroyAllWindows();
}
```

# 結果
<img width="477" alt="output.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/a5573019-dc6f-e81b-622e-197560f35c6c.png">
メソッド内では`Canny`(細線化)を利用しているそうですが、元ネタである[Outdoor Place Recognition in Urban Environments using Straight Lines](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.646.5683&rep=rep1&type=pdf) をガチ読みしないとわからんとです。:scream:


#おわりに
`createLSDDetector`を使いたい場合は3系をダウンロードしてbuildすると使えるかもしれませんが環境を整えるのは面倒です。 画像同士の比較ですがパラメータが4つしかないですが最近傍探索でマッチングするしかなさそうです。公式Docにあるのに[Line Features Tutorial](https://docs.opencv.org/master/df/dfa/tutorial_line_descriptor_main.html)が使えないのがマジ草です。 今回はC++で実装したのですがPythonでもできます。時間があったら追記します。

# 参考になりそうなリンク
- Lilian Zhang and Reinhard Koch. An efficient and robust line segment matching approach based on lbd descriptor and pairwise geometric consistency. Journal of Visual Communication and Image Representation, 24(7):794–805, 2013. (無料では公開されていないっぽい)
- [Outdoor Place Recognition in Urban Environments using Straight Lines](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.646.5683&rep=rep1&type=pdf)
- [OpenCVからLineSegmentDetector(LSD)が消えた](https://www.kouken-party.info/2019/05/17/opencv%E3%81%8B%E3%82%89linesegmentdetectorlsd%E3%81%8C%E6%B6%88%E3%81%88%E3%81%9F/)
- [license problem in descriptor.hpp](https://github.com/opencv/opencv_contrib/issues/2016)