OpenCV入門【3.0対応】(2)

OpenCV入門【3.0対応】(2)

OpenCV 3.0の新機能(+ 次バージョンのロードマップ)

2015年11月10日

2015年6月に大望のOpenCVのメジャーバージョンアップ「3.0」が登場した。この新バージョンの新機能をモジュールごとに説明し、次バージョン3.1のロードマップを簡単に紹介する。

@dandelion1124(dandelion's log
  • このエントリーをはてなブックマークに追加

1. OpenCV 3.0のロードマップ

1.1 OpenCV 3.0

 OpenCVは、2015年6月にメジャーバージョンアップが実施され、3.0がリリースされました。また、前回の記事でも述べたようにOpenCV 3.0ではさまざまな機能が追加されています。今回の記事では追加された機能をピックアップして使用例を交えながら紹介します。

1.2 OpenCV 3.1

 ここでは、次バージョン(OpenCV 3.1)のロードマップについても触れておきたいと思います。

 公式の開発進捗(しんちょく)議事録であるOpenCV Meeting notes(2015/10/6)に、

OpenCV 3.1 release is planned for end of November-beginning of December

という記述があり、(少なくとも2015/10/6時点では)2015年末にOpenCV 3.1がリリースされる予定となっているようです。

 さらに、

  • Will include all of the summer of code work
  • Will take better advantage of Intel's IPP ICV
  • Better HAL (Hardware Acceleration Layer) support.
    • Intrinsics to better support SSE and Neon (same code, 2 deployments).

という記述もあることから、OpenCV Google Summer of Code 2015の成果物取り込みによる機能追加だけでなく、IPPICVのさらなる活用やHALの改善によるパフォーマンス向上なども取り組まれるようです。

2. OpenCV 3.0の新機能紹介

 この章ではOpenCV 3.0の新機能紹介をモジュールごとに紹介します。今回紹介するモジュールは以下の通りです。

 また、ユーザーから寄贈された追加機能がまとめられているリポジトリopencv_contribに導入された新機能については別の記事で紹介予定です。

▲新機能の一覧に戻る

2.1. coreモジュール

CPU/GPU実装のカプセル化: UMat

 OpenCV 3.0よりCPU/GPU実装のカプセル化を行うための仕組みであるT-API(transparent API)が導入されました。そのため、OpenCVユーザーは、T-APIで提供されるUMatと呼ばれるデータ構造を用いて実装することで、CPU/GPUどちらでも動作する処理を同一コードで記述できます。

 図1にUMatを用いた場合の内部処理の概要を示します。

  1. OpenCLが使える環境かどうかをチェックする
  2. OpenCLが使える環境であればOpenCVで用意しているOpenCL実装を用い、そうでなければMat(=CPU版の、画像データの入れもの)の実装を用いる

 ただし、図1の青で囲んだ内部処理はOpenCV内部に隠ぺいされているため、OpenCVユーザーがこれらの処理を記述する必要はありません。

UMatの内部処理
図1 UMatの内部処理

 また、図2は、「CVPR 2015チュートリアル資料」(英語)で紹介されているT-APIの計測結果です。この結果よりT-API(OpenCL)を用いることで、Matを用いた場合に比べて高速化できていることが分かります。ただし、計測環境によって効果は異なるので参考程度とした方がよいでしょう。

図2 T-APIによる高速化(CVPR 2015チュートリアル資料から引用)
●サンプルコード(CPU/GPU実装のカプセル化: UMat)

 UMatを使ってグレースケール化を行うサンプルコードを以下に示します。

C++
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>

#include <iostream>

int main(int argc, char *argv[])
{
  // (1)画像データをファイル(この例では「lena.jpg」)から読み込む
  cv::Mat img = cv::imread("lena.jpg", cv::IMREAD_COLOR);

  // 画像の読み込みに失敗したらエラー終了する
  if (img.empty())
  {
    std::cerr << "Failed to open image file." << std::endl;
    return -1;
  }

  // (2)UMatのインスタンスを定義する
  cv::UMat u_img, u_gray;

  // (3)MatのデータをUMatにコピーする
  img.copyTo(u_img);

  // (4)UMatのインスタンスを用いてグレースケール化を行う
  cv::cvtColor(u_img, u_gray, cv::COLOR_BGR2GRAY);

  return 0;
}
サンプルコード(CPU/GPU実装のカプセル化: UMat)
●参考URL

▲新機能の一覧に戻る

2.2. shapeモジュール

2D shape matching

 OpenCV 3.0より形状に関する処理を行うためのshapeモジュールが追加されています。このモジュールでは、輪郭線(contour)の形状の距離(距離が短いほど形状が近い)を算出するメソッドShapeDistanceExtractor::computeDistanceが提供されています。このメソッドを用いることで形状のマッチングを行うことができます。

●サンプルコード(2D shape matching)

 shapeモジュールのShapeDistanceExtractor::computeDistanceメソッドを用いて形状のマッチングを行うサンプルコードを以下に示します。

C++
#include <opencv2/core.hpp>
#include <opencv2/shape.hpp>
#include <opencv2/imgcodecs.hpp>

#include <iostream>

static std::vector<cv::Point> simpleContour(const cv::Mat& src)
{
  std::vector<std::vector<cv::Point>> contours;
  std::vector<cv::Point> contour_points;
  cv::findContours(src, contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
  size_t contours_size = contours.size();

  for (size_t border = 0; border < contours_size; border++)
  {
    size_t contour_size = contours[border].size();
    for (size_t p = 0; p < contour_size; p++)
    {
      contour_points.push_back(contours[border][p]);
    }
  }
  return contour_points;
}

int main(int argc, char** argv)
{
  if (argc < 3)
  {
    std::cerr << "Usage: " << argv[0] << " <filename1> <filename2>" << std::endl;
    return -1;
  }

  // (1)画像データをファイルから読み込む
  cv::Mat img1 = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
  cv::Mat img2 = cv::imread(argv[2], cv::IMREAD_GRAYSCALE);

  // 画像の読み込みに失敗したらエラー終了する
  if (img1.empty() || img2.empty())
  {
    std::cerr << "Failed to open image file." << std::endl;
    return -1;
  }

  // (2)画像データから輪郭線(contour)データを生成する
  std::vector<cv::Point> contour1 = simpleContour(img1);
  std::vector<cv::Point> contour2 = simpleContour(img2);

  // (3)輪郭線同士の距離を算出する
  cv::Ptr<cv::ShapeContextDistanceExtractor> mysc = 
    cv::createShapeContextDistanceExtractor();
  float distance = mysc->computeDistance(contour1, contour2);

  std::cout << "Distance between " << argv[1] << " and " << 
    argv[2] << " is: " << distance << std::endl;

  return 0;
}
サンプルコード(2D shape matching)
●実行結果

 前述のサンプルコードの実行結果は以下の通りです。形状が近いものについてdistanceの値が小さくなっていることが分かります。

ファイル名画像shape1との距離(distance)
shape1.png shape1.png 0.0
shape2.png shape2.png 2.46439
shape3.png shape3.png 106.038
shape4.png shape4.png 3.2247
サンプルコードの実行結果

▲新機能の一覧に戻る

2.3 features2dモジュール

KAZE/AKAZE特徴量

 OpenCV 3.0よりfeatures2dモジュールにKAZE特徴量、AKAZE特徴量の実装が追加されました。KAZE特徴量、AKAZE特徴量については作者のホームページ(英語)を参照してください。

●サンプルコード(AKAZE特徴量)

 AKAZE特徴量を用いたサンプルコードを以下に示します。

C++
#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/imgcodecs.hpp>

#include <iostream>
#include <vector>

int main(int argc, const char** argv)
{
  // (1)画像データをファイル(この例では「lena.jpg」)から読み込む
  cv::Mat img = cv::imread("lena.jpg", cv::IMREAD_COLOR);

  // 画像の読み込みに失敗したらエラー終了する
  if (img.empty())
  {
    std::cerr << "Failed to open image file." << std::endl;
    return -1;
  }

  cv::Mat dst, descriptors;
  std::vector<cv::KeyPoint> keyPoints;

  // (2)検出器(AKAZE)を初期化する
  cv::Ptr<cv::AKAZE> detector = cv::AKAZE::create();

  // (3)キーポイント検出およびディスクリプター計算を行う
  detector->detectAndCompute(img, cv::noArray(), keyPoints, descriptors);

  // (4)キーポイントを描画する
  cv::drawKeypoints(img, keyPoints, dst, 
    cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

  return 0;
}
サンプルコード(AKAZE特徴量)
●実行結果(AKAZE特徴量)
図3 入力画像
図4 キーポイント描画結果
●参考URL

▲新機能の一覧に戻る

2.4 photoモジュール

Non-photorealistic rendering

 油絵や鉛筆画などの表現を持つ画像を生成するphotoモジュールに機能が追加されています。ここでは以下の2つの機能(メソッド)について例を交えて紹介します。

  • cv::edgePreservingFilter エッジ情報を保持しつつ平滑化を行う
  • cv::pencilSketch 鉛筆画風にした画像を生成する

 これらのAPIの詳細は公式ドキュメント(英語)を参照してください。

●実行結果(Non-photorealistic rendering)

 図5が入力画像、図6がcv::edgePreservingFilterメソッドにより図7がcv::pencilSketchメソッドを用いて鉛筆画風に加工した結果です。これら処理を試したい方は公式のサンプルコードを参照してください。

図5 入力画像
図6 エッジ情報を保持した平滑化
図7 鉛筆画風に加工した結果
Local Color Change

 photoモジュールで提供されるcv::colorChangeメソッドを用いることで引数maskで指定された領域に対してシームレスに色を変更できます。このAPIの詳細は公式ドキュメント(英語)を参照してください。

●実行結果

 図8が入力(src)画像、図9がマスク(mask)画像、図13がcv::colorChangeメソッドを用いてmaskで指定された領域に対して色を変更している例です。この機能を試したい方は公式のサンプルコードを参照してください。

図8 src画像
図9 mask画像
図10 出力画像
Illumination Change

 photoモジュールで提供されるcv::illuminationChangeメソッドを用いることで引数maskによって指定された領域に対して見掛け上のローカルな照明を変更できます。このAPIの詳細は公式ドキュメント(英語)を参照してください。

●実行結果

 図11がsrc画像、図12がmask画像、図13がcv::illuminationChangeメソッドを用いて鏡面反射を軽減させている例です。この機能を試したい方は公式のサンプルコードを参照してください。

図11 src画像
図12 mask画像
図13 出力画像
Seamless cloning

 photoモジュールで提供されるcv::seamlessCloneメソッドを用いることで複数の画像をシームレスに合成できます。このAPIの詳細は公式ドキュメントを参照してください。

●実行結果

 図14が合成元(src)画像、図15が合成先(dst)画像、図16がmask画像、図17がcv::seamlessCloneメソッドを用いて2つの画像を合成している例です。この機能を試したい方は公式のサンプルコードを参照してください。

図14 src画像
図15 dst画像
図16 mask画像
図17 合成結果

▲新機能の一覧に戻る

2.5 imgprocモジュール

ラベリング

 OpenCV 3.0からimgprocモジュールで、以下のラベリング専用APIが提供されるようになりました。そのため、これらのAPIを使うことで、簡単にラベリングを行えるようになっています。

  • cv::connectedComponents 簡易版ラベリングAPI
  • cv::connectedComponentsWithStats 詳細な情報(面積、重心、幅、高さなど)を取得できるラベリングAPI

 これらのAPIの詳細は公式APIドキュメントの説明(英語)を参照してください。

 また、筆者のWikiでもAPIについて解説していますのでご参考ください。

●サンプルコード(ラベリング)

 筆者のWikiで、connectedComponentsメソッドを使用したラベリングのサンプルコードを公開しています。

●実行結果

 前述のサンプルコードの実行結果は以下の通りです。

図18 入力画像
図19 出力画像(ラベルごとに色分け)
●参考URL

▲新機能の一覧に戻る

2.6 imgcodecsモジュール

WebPフォーマット対応

 WebPは、グーグル社によって開発されている静止画フォーマットで、Google ChromeOperaといったWebブラウザー、PicasaImageMagickIrfanViewといった画像編集ツールもこのフォーマットをサポートしています。

 OpenCV 3.0よりimgcodecsモジュールでWebPフォーマットの入出力に対応しており、cv::imreadcv::imwriteメソッドでWebPの入出力を行うことができます。

●サンプルコード(WebP形式の入出力)

 WebP形式の入出力を行うサンプルコードを以下に示します。

C++
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>

int main(int argc, char *argv[])
{
  // 幅320px、高さ240px、3チャンネルのインスタンスを生成する
  cv::Mat img(cv::Size(320, 240), CV_8UC3, cv::Scalar(0, 0, 255));

  // (1)画像データをWebP形式のファイルに書き出す
  cv::imwrite("image.webp", img);

  // (2)画像データをWebP形式のファイル(この例では「image.webp」)から読み込む
  cv::Mat img2 = cv::imread("image.webp", cv::IMREAD_UNCHANGED);

  return 0;
}
サンプルコード(WebP形式の入出力)

▲新機能の一覧に戻る

2.7 vizモジュール

2D/3Dデータの可視化

 OpenCV 3.0よりvizモジュールで、2D/3Dデータの可視化を行えるようになっています。vizモジュールの内部ではVTK(The Visualization ToolKit)を使用して2D/3Dデータの可視化を行っています。

●実行結果

 図20は、vizモジュールを用いて3Dデータをメッシュ表示した例です。

図20 3Dデータの可視化

3. おわりに

 今回は、OpenCV 3.0に関する以下の内容について解説しました。

  • OpenCV 3.0のロードマップ
  • OpenCV 3.0の新機能紹介

 次回は、OpenCV 3.0の環境構築方法について解説します。

※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

1. OpenCVとは? 最新3.0の新機能概要とモジュール構成

オープンソースのコンピューター・ビジョン・ライブラリ「OpenCV」 3.0のリリースに合わせて連載再始動! 今回はOpenCVの概要と基本機能を紹介する。ベータ→正式版に合わせて改訂。

2. 【現在、表示中】≫ OpenCV 3.0の新機能(+ 次バージョンのロードマップ)

2015年6月に大望のOpenCVのメジャーバージョンアップ「3.0」が登場した。この新バージョンの新機能をモジュールごとに説明し、次バージョン3.1のロードマップを簡単に紹介する。

3. OpenCVの環境構築(OpenCV 3.0/3.1)

OpenCV 3環境の構築方法として、「公式パッケージを使ったインストール」「CMakeを使ったライブラリのビルド」「NuGetを使ったパッケージインストール」の3ケースを解説。バージョン2.4.9から3.0/3.1に合わせて改訂。

4. 初めてのOpenCV開発 ― Visual Studio/CMake/NuGetでプロジェクト作成【OpenCV 3.0/3.1】

OpenCVを使ったアプリケーションのプロジェクト作成方法として、「Visual Studio」「CMake」「NuGet」の3つの方法を解説する。

5. 初めてのOpenCV開発 ― coreモジュール【OpenCV 3.1.0】

OpenCVのcoreモジュールの概要を解説。そのMatクラスを使って画像データを扱う方法や、ユーティリティ関数、OpenCV 3.0より導入されたUMatクラスを紹介する。

Twitterでつぶやこう!


Build Insider賛同企業・団体

Build Insiderは、以下の企業・団体の支援を受けて活動しています(募集概要)。

ゴールドレベル

  • グレープシティ株式会社
  • 日本マイクロソフト株式会社