Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

【第27回コンピュータビジョン勉強会@関東】OpenCV 便利Tips紹介

【第27回コンピュータビジョン勉強会@関東】OpenCV 便利Tips紹介

  • Be the first to comment

【第27回コンピュータビジョン勉強会@関東】OpenCV 便利Tips紹介

  1. 1. OpenCV 便利Tips紹介 第27回コンピュータビジョン勉強会@関東 2015/1/31 @dandelion1124
  2. 2. 自己紹介 Twitter ID:@dandelion1124 • 学生時代は画像処理の研究に従事。 • 研究室でOpenCV Tipsサイトを作っていたらOpenCV関連書 籍(OpenCVプログラミングブック)を執筆。 • 現在は都内勤務エンジニア。 • Build InsiderにてOpenCV入門 (http://www.buildinsider.net/small/opencv)を連載中。 blog: http://www.atinfinity.info/blog/ wiki: http://www.atinfinity.info/wiki/
  3. 3. 本日のアジェンダ • OpenCVメモリ使用量を計測する • oclMatで自作OpenCLカーネルを動かす • OpenCVでラベリングを行う
  4. 4. OpenCVメモリ使用量を計測する
  5. 5. OpenCVメモリ使用量を計測する • 「Hacking OpenCV for fun and profit」(http://computer- vision-talks.com/articles/hacking-opencv-for-fun-and-profit/) というブログ記事にて「OpenCVを拡張したメモリ使用量計測 方法」が紹介されています。 • 最近、公式へのプルリクエストも行われている模様。 (https://github.com/Itseez/opencv/pull/3640) – そのうち、公式に取り込まれるかも? ということで、なんだか便利そうなこの機能を試してみました!
  6. 6. OpenCVメモリ使用量を計測する • 使い方 – OpenCVメモリ使用量計測機能が入ったソース (https://github.com/BloodAxe/opencv/tree/memory- snapshots)を取得する – CMakeで「ENABLE_MEMORY_SNAPSHOTS」をONにして OpenCVをビルドする – 計測したい箇所をMEASURE_MEMORYマクロで囲む! 【注意】OpenCV内部で確保したメモリ使用量のみ計測可。
  7. 7. サンプルコード(OpenCVメモリ使用量計測) #include <opencv2/core/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #define ENABLE_MEASURE_MEMORY #ifndef ENABLE_MEASURE_MEMORY #define MEASURE_MEMORY(x) {x;} #else #define MEASURE_MEMORY(x) { ¥ size_t memOnStart = cv::memorySnapshot().allocatedMemory; x;¥ size_t memOnEnd = cv::memorySnapshot().allocatedMemory; ¥ std::cout << #x << "," << "¥t" << memOnStart / (1024.0*1024.0) << "[MB]" << ¥ " -> " << ¥ memOnEnd / (1024.0*1024.0) << "[MB]" << std::endl; } #endif int main(int argc, char** argv) { cv::Mat src, dst; MEASURE_MEMORY(src = cv::imread("lena.jpg", cv::IMREAD_COLOR)); MEASURE_MEMORY(cv::resize(src, dst, cv::Size(), 5.0, 5.0)); MEASURE_MEMORY(dst.release()); return 0; } MEASURE_MEMORYマクロで 囲んで実行 計測用マクロ定義
  8. 8. サンプルコード(OpenCVメモリ使用量計測) #define MEASURE_MEMORY(x) { ¥ size_t memOnStart = cv::memorySnapshot().allocatedMemory; x;¥ size_t memOnEnd = cv::memorySnapshot().allocatedMemory; ¥ std::cout << #x << "," << "¥t" << memOnStart / (1024.0*1024.0) << "[MB]" << ¥ " -> " << ¥ memOnEnd / (1024.0*1024.0) << "[MB]" << std::endl; } ソースコード(計測用マクロ) MEASURE_MEMORYマクロの概要 ① 処理xを行う前のOpenCVメモリ使用量(memOnStart)を取得する ② 処理xを実行する ③ 処理xを行った後のOpenCVメモリ使用量(memOnEnd)を取得する ④ memOnStart、 memOnEndの値を標準出力する ① ② ③ ④
  9. 9. src = cv::imread("lena.jpg", cv::IMREAD_COLOR), 0.332099[MB] -> 1.0821[MB] cv::resize(src, dst, cv::Size(), 5.0, 5.0), 1.0821[MB] -> 19.8321[MB] dst.release(), 19.8321[MB] -> 1.0821[MB] 標準出力結果 サンプルコード(OpenCVメモリ使用量計測) cv::Mat src, dst; MEASURE_MEMORY(src = cv::imread("lena.jpg", cv::IMREAD_COLOR)); MEASURE_MEMORY(cv::resize(src, dst, cv::Size(), 5.0, 5.0)); MEASURE_MEMORY(dst.release()); ソースコード(抜粋) 実行した処理 処理前のメモリ使用量 処理後のメモリ使用量
  10. 10. サンプルコード(OpenCVメモリ使用量計測) src = cv::imread("lena.jpg", cv::IMREAD_COLOR), 0.332099[MB] -> 1.0821[MB] cv::resize(src, dst, cv::Size(), 5.0, 5.0), 1.0821[MB] -> 19.8321[MB] dst.release(), 19.8321[MB] -> 1.0821[MB] cv::Mat src, dst; MEASURE_MEMORY(src = cv::imread("lena.jpg", cv::IMREAD_COLOR)); MEASURE_MEMORY(cv::resize(src, dst, cv::Size(), 5.0, 5.0)); MEASURE_MEMORY(dst.release()); 画像データを解放するとメモリ使用量も減少していることがわかる。 サンプルコードは、https://gist.github.com/atinfinity/6b837b3859a5252d4cb8で公開。 ソースコード(抜粋) 標準出力結果
  11. 11. oclMatで 自作OpenCLカーネルを動かす
  12. 12. oclMatとは? • OpenCLデバイス上で画像処理を行うために用いる OpenCVのデータ構造 • MatやGpuMatと基本的に使い方が同じ oclMatの詳細を知りたい方は過去の発表資料を参照ください。 http://www.slideshare.net/YasuhiroYoshimura/gpgpu2opencvopencloclmat
  13. 13. 自作OpenCLカーネルを動かす方法 • oclMatで実行されるカーネルは基本的にあらかじめ OpenCVで既に用意されたOpenCLカーネル • あまり知られていません(?)が、ユーザ自作の OpenCLカーネルを動かす方法も提供されています! – ただし、公式ドキュメントには使い方が一切書かれていないことから、 しぶしぶソースを読んで調べました・・・
  14. 14. oclMatで自作OpenCLカーネルを動作させる おおまかな手順は以下の通り。 ① OpenCLカーネルを記述 ② ①からプログラムオブジェクトを作成 ③ ocl::openCLExecuteKernelInterop関数に画像データ、②で 作成したプログラムオブジェクトを渡して実行 これで俺々OpenCLカーネルを作って 動かせる!嬉しい!!! 自作OpenCLカーネルを動かす方法
  15. 15. サンプルコード(ネガポジ変換) const char *KernelSource = "¥n" ¥ "__kernel void negaposi_C1_D0( ¥n" ¥ " __global uchar* input, ¥n" ¥ " __global uchar* output) ¥n" ¥ "{ ¥n" ¥ " int i = get_global_id(0); ¥n" ¥ " output[i] = 255 - input[i]; ¥n" ¥ "}¥n"; ①OpenCLカーネルを記述 【注意】 カーネルが対象とするチャンネル数、デプスを 表すような関数名にする必要がある。 この例では、 C1:チャンネル数が1 D0:デプスがCV_8U(=0) 向けのカーネルであることを表している。 画素値(出力) = 255 – 画素値(入力)という単純なカーネル 自作OpenCLカーネル
  16. 16. サンプルコード(ネガポジ変換) 自作OpenCLカーネル実行処理(抜粋) cv::ocl::ProgramSource program("negaposi", KernelSource); std::size_t globalThreads[3]={mat_src.cols * mat_src.rows, 1, 1}; std::vector<std::pair<size_t , const void *> > args; args.push_back( std::make_pair( sizeof(cl_mem), (void *) &ocl_src.data )); args.push_back( std::make_pair( sizeof(cl_mem), (void *) &ocl_dst.data )); cv::ocl::openCLExecuteKernelInterop(cv::ocl::Context::getContext(), program, "negaposi", globalThreads, NULL, args, channels, depth, NULL); サンプルコードは、https://gist.github.com/atinfinity/8c25c8fb1b3708aa0944で公開。 ②①のOpenCLカーネルから プログラムオブジェクトを作成 ③ocl::openCLExecuteKernelInterop関数に画像データ、 ②で作成したプログラムオブジェクトを渡して実行
  17. 17. ネガポジ変換の結果 入力画像 出力画像(ネガポジ変換)
  18. 18. OpenCVでラベリングを行う
  19. 19. OpenCVでラベリングを行う(1/2) OpenCV 2.xでライブラリ等を用いてラベリングを行う場合、 ざっくりと以下の選択肢があります。 • OpenCVBlobsLib(http://opencvblobslib.github.io/opencvblobslib/)を使う – pthreadを用いて並列化されており、OpenCVとの親和性も高い。 – 2014年3月で更新が止まっている。また、GNU LGPL v3なのがややネック。 • 井村先生のLabelingクラス(http://oshiro.bpe.es.osaka- u.ac.jp/people/staff/imura/products/labeling)を使う – 便利関数も用意されている。ライセンスも修正BSDなので使いやすい。 – ただし、OpenCVのMatを直接扱えない。 • cv::findContours関数を使って自前実装する – もともとラベリング専用の関数ではないので細かいところがイマイチ。
  20. 20. OpenCVでラベリングを行う(2/2) 今更感はありますが、ついにOpenCV 3.0からラベリング専用APIが 提供されます!嬉しい!! • 簡易版API – int connectedComponents(InputArray image, OutputArray labels, int connectivity=8, int ltype=CV_32S) • もう少し細かい情報(面積、重心、幅 、高さ etc…)が取れるAPI – int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity=8, int ltype=CV_32S) • 詳細は公式ドキュメント (http://docs.opencv.org/master/modules/imgproc/doc/structural_analysis_and_shape _descriptors.html#connectedcomponents)を参照ください。
  21. 21. サンプルコード(抜粋) #include <opencv2/core/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> int main(int argc, char** argv) { cv::Mat src = cv::imread("input.png", cv::IMREAD_GRAYSCALE); cv::Mat bin; cv::threshold(src, bin, 0, 255, cv::THRESH_BINARY|cv::THRESH_OTSU); cv::Mat labelImage(img.size(), CV_32S); int nLabels = cv::connectedComponents(bin, labelImage, 8); return 0; } 画像読み込み 二値化 ラベル用画像生成 ※CV_32S or CV_16Uとする必要あり ラベリング実行。 戻り値がラベル数。 ラベリングAPIは imgprocモジュールにて提供 このサンプルでは8近傍で ラベリング処理を行う
  22. 22. ラベリング結果 サンプルコードは、https://gist.github.com/atinfinity/e725e659b4bd68fb3fb4で公開。 入力画像 ラベリング結果 (ラベル毎に色を割り振っている)
  23. 23. おわり

    Be the first to comment

    Login to see the comments

  • tokoik

    Jan. 28, 2015
  • KanSakamoto

    Jan. 28, 2015
  • satoshibfujimoto

    Jan. 28, 2015
  • pmonster

    Jan. 29, 2015
  • takashiishibashi7

    Jan. 31, 2015
  • ohgochi

    Feb. 3, 2015
  • atsushi_okazawa

    Mar. 21, 2015
  • akihiroHayama

    Apr. 26, 2015
  • kazuhikokobayashi568

    May. 3, 2015
  • tishige

    May. 15, 2015
  • NobuhikoAsada

    Nov. 19, 2015
  • ysaka

    Jan. 20, 2017
  • m0tchy1

    Oct. 1, 2017

【第27回コンピュータビジョン勉強会@関東】OpenCV 便利Tips紹介

Views

Total views

5,293

On Slideshare

0

From embeds

0

Number of embeds

348

Actions

Downloads

42

Shares

0

Comments

0

Likes

13

×