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


背景

OpenCVで油絵エフェクトは1行でかけるとのことです。(C++限定)と同様に
Tutorials for contrib modules(opencv-contrib-python)で最近作成されたモジュールで割とすぐに確認できそうなのを見つけて実装しようと思っています。
今回は

特徴"線"抽出

です。

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

開発。。。したけど

Line Features Tutorial にあるコードを元に実装しようとしたのですが、

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)が消えたlicense problem in descriptor.hppを見るとライセンスの問題で4系から特徴線を抽出するモジュールが削除されたみたいです。

開発(代替)

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

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

元画像っす

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

 -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_ximgproc
#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();
}

結果


メソッド内ではCanny(細線化)を利用しているそうですが、元ネタであるOutdoor Place Recognition in Urban Environments using Straight Lines をガチ読みしないとわからんとです。

おわりに

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

参考になりそうなリンク