第5回 初めてのOpenCV開発 ― coreモジュール【OpenCV 3.1.0】OpenCV入門【3.0対応】(1/2 ページ)

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

» 2016年08月17日 05時00分 公開
「OpenCV入門【3.0対応】」のインデックス

連載目次

ご注意:本記事は、@IT/Deep Insider編集部(デジタルアドバンテージ社)が「www.buildinsider.net」というサイトから、内容を改変することなく、そのまま「@IT」へと転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

1. はじめに

 前回、OpenCVを使ったアプリケーションのプロジェクト作成方法について解説を行いました。今回はOpenCVのcoreモジュールについて解説します。

 以下の表に、今回紹介するcoreモジュールの機能の概要をまとめました。

モジュール名 機能の概要
core 画像・行列データ構造の提供、配列操作、XMLおよびYAML入出力、コマンドラインパーサー、ユーティリティ機能など
モジュール(core)の概要

 また、筆者が確認した環境は以下の通りです。

項目 内容
OpenCVバージョン OpenCV 3.1.0
Visual Studio Visual Studio 2013 Update5
ビルド構成 x64Release
OS Windows 10 Pro(64bit)
筆者が確認した環境

2. Matクラス

 OpenCVでは画像データを格納するデータ構造としてMatクラスを提供しています。OpenCVの多くの関数の入出力は、Matクラスを介して行われます。そのため、このMatクラスを取り扱うに当たり、以下の3つの基本的な処理の方法について、例を用いながら解説します。

  • インスタンス生成
  • プロパティ取得
  • ピクセルへのアクセス

2.1 インスタンス生成

 ここではMatクラスのインスタンス生成方法について解説します。画像ファイルを読み込んでインスタンスを生成する方法もありますが、その方法については次回(imgcodecsモジュール)の記事で紹介します。

 そこで、画像の幅320px、高さ240px、赤色の画像データ生成を行う下記のコードを例に用いながら、インスタンス生成方法を解説します。

cv::Mat img(cv::Size(320, 240), CV_8UC3, cv::Scalar(0, 0, 255));

画像の幅320px、高さ240px、赤色の画像データ生成を行うコード

 上記コードでポイントとなる項目と意味は以下の通りです。

項目 意味
cv::Size(320, 240) 画像サイズ(幅320px、高さ240px)
CV_8UC3 ビット深度=符号なしの8bit整数、チャンネル数=3
cv::Scalar(0, 0, 255) 画像の色。この例では赤色B=0G=0R=255
上記コードのポイントと意味

 以降は、画像のプロパティを指定するために用いる、

  • ビット深度・チャンネル数
  • cv::Size
  • cv::Scalar

についてもう少し詳しく説明を行います。

2.1.1 ビット深度・チャンネル数

 OpenCVでは、

CV_<ビット深度>{U|S|F}C<チャンネル数>
Uは符号なし、Sは符号付き、Fは浮動小数点数を表す

という表記によって画像のビット深度とチャンネル数を表現しています。

 そのため、前述のコードにある、

CV_8UC3

は、

  • ビット深度=符号なしの8bit整数
  • チャンネル数=3

という意味を表しています。

2.1.2 cv::Size

 OpenCVでは、cv::Sizeというデータ構造を使うことで画像のサイズを指定できます。cv::Sizeを使う場合、第1引数がwidth(画像の幅)、第2引数がheight(画像の高さ)となります。

 そのため、前述のコードにある、

cv::Size(320, 240)

画像サイズ(幅320px、高さ240px)という意味を表しています。

2.1.3 cv::Scalar

 OpenCVでは、cv::Scalarというデータ構造を使うことで画像の色を指定できます。ただしOpenCVの画像データは、RGB表色系の場合、cv::Scalarに対してBGRの順に指定する点に注意ください。

 そのため、前述のコードにある、

cv::Scalar(0, 0, 255)

は、赤色R=255G=0B=0)という意味を表しています。

2.2 プロパティ取得

 Matクラスのメソッドを呼ぶことで画像データの各種プロパティを取得できます。以降、各種プロパティを取得するメソッドについて例を用いながら紹介します。

2.2.1 rows、cols

 Matクラスは画像データだけでなく、行列も取り扱うことができます。このことからMatクラスには、行列の行数を参照するrows、列数を参照するcolsが、メンバー変数として定義されています。

 Matクラスのメンバー変数rowscolsを参照することで、画像の高さ/幅を取得できます。

  • cols: 画像の幅(行列の列数に対応)
  • rows: 画像の高さ(行列の行数に対応)

 以下に画像の幅と高さを取得するサンプルコードを示します。

#include <opencv2/core.hpp>
#include <iostream>

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

  // 画像の幅を表示する
  std::cout << "width: " << img.cols << std::endl;

  // 画像の高さを表示する
  std::cout << "height: " << img.rows << std::endl;

  return 0;
}

画像の幅と高さを取得するサンプルコード

 このサンプルコードを実行したときの標準出力は以下の通りです。この例では、imgは幅320px、高さ240pxなので以下のような標準出力が行われます。

width: 320
height: 240


上記のサンプルコードを実行したときの標準出力

2.2.2 channelsメソッド

 Matクラスのchannelsメソッドにより画像のチャンネル数を取得できます。グレースケール画像の場合は「1」、カラー画像の場合は「3」、アルファチャンネル付きのカラー画像の場合は「4」が返ってきます。

 以下に画像のチャンネル数を取得するサンプルコードを示します。

#include <opencv2/core.hpp>
#include <iostream>

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

  // チャンネル数を表示する
  std::cout << "channels: " << img.channels() << std::endl;

  return 0;
}

画像のチャンネル数を取得するサンプルコード

 このサンプルコードを実行したときの標準出力は以下の通りです。この例では、img3チャンネルなので以下のような標準出力が行われます。

channels: 3


上記のサンプルコードを実行したときの標準出力

2.2.3 depthメソッド

 Matクラスのdepthメソッドにより、画像のビット深度を取得できます。ただし、depthメソッドの戻り値はビット深度の値そのものではなく、OpenCV内に定義される定数値である点に注意してください。

 以下にinclude\opencv2\core\cvdef.hファイルで定義される定数の定義部を引用します。

#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6

OpenCV内に定義される定数値(cvdef.hファイルから引用)

 また、OpenCV内に定義されるビット深度名とそれらの意味は以下の通りです。

ビット深度名 意味
CV_8U 符号なしの8bit整数( 0((〜))255 )
CV_8S 符号付きの8bit整数( -128((〜))127 )
CV_16U 符号なしの16bit整数( 0((〜))65535 )
CV_16S 符号付きの16bit整数( -32768((〜))32767 )
CV_32S 符号付きの32bit整数( -2147483648((〜))2147483647 )
CV_32F 32bit浮動小数点数 ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F 64bit浮動小数点数( -DBL_MAX..DBL_MAX, INF, NAN )
OpenCV内に定義されるビット深度名と意味

 以下に画像のビット深度を取得するサンプルコードを示します。

#include <opencv2/core.hpp>
#include <iostream>
 
// ビット深度名を表示する自作関数
void printDepth(cv::Mat& img)
{
  // 画像のビット深度を取得する
  unsigned int depth = img.depth();

  std::string strDepth = 
    (
      depth == CV_8U  ? "CV_8U"  :
      depth == CV_8S  ? "CV_8S"  :
      depth == CV_16U ? "CV_16U" :
      depth == CV_16S ? "CV_16S" :
      depth == CV_32S ? "CV_32S" :
      depth == CV_32F ? "CV_32F" :
      depth == CV_64F ? "CV_64F" :
      "Other"
    );
  std::cout << "depth: " << strDepth << std::endl;
}
 
int main(int argc, const char* argv[])
{
  // 幅320px、高さ240px、3チャンネルのインスタンスを生成する
  cv::Mat img(cv::Size(320, 240), CV_8UC3, cv::Scalar(0, 0, 255));
 
  // ビット深度名を表示する自作関数
  printDepth(img);
 
  return 0;
}

ビット深度を取得するサンプルコード

 このサンプルコードを実行したときの標準出力は以下の通りです。この例では、imgのビット深度は符号なしの8bit整数であるため、以下のような標準出力が行われます。

depth: CV_8U


上記のサンプルコードを実行したときの標準出力

2.3 ピクセルへのアクセス

 ここでは任意のピクセルの画素値にアクセスする方法の1つであるatメソッドについて紹介します。その他のアクセス方法については、

を参考ください。

2.3.1 画素値の参照

 Matクラスのatメソッドを以下のように呼び出すことで、変数imgにおける座標(x, y)の画素値を参照できます。ただし、このときatメソッドに渡すパラメーターは(y, x)の順に指定する必要がある点に注意が必要です。

img.at<cv::vec3b>(y, x);

Matクラスのatメソッドを呼び出して画素値を参照する方法

 以下に画素値を参照するサンプルコードを示します。

#include <opencv2/core.hpp>
#include <iostream>

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

    // (1)座標(0, 100)の画素値を取得する
    // atに渡すパラメーターは(y, x)の順である点に注意
    // Matのデータは(RGB表色系の場合)BGRの順に並んでいる点に注意
    cv::Vec3b intensity = img.at<cv::Vec3b>(100, 0);
    uchar blue  = intensity.val[0];
    uchar green = intensity.val[1];
    uchar red   = intensity.val[2];

    // (2)画素値を表示する
    std::cout << "R: " << (unsigned int)red   << std::endl;
    std::cout << "G: " << (unsigned int)green << std::endl;
    std::cout << "B: " << (unsigned int)blue  << std::endl;

    return 0;
}

画素値を参照するサンプルコード

 このサンプルコードを実行したときの標準出力は以下の通りです。この例では、img(全てのピクセルが赤色の画像)における座標(0, 100)の画素値は赤色であるため、以下のような標準出力が行われます。

R: 255
G: 0
B: 0


上記のサンプルコードを実行したときの標準出力

2.3.2 画素値の変更

 atメソッドを以下のように呼び出すことで、変数imgにおける座標(x, y)の画素値を変更できます。また、このときatメソッドに渡すパラメーターは(y, x)の順序である点と、Matのデータは(RGB表色系の場合)BGRの順に並んでいる点に注意が必要です(redValuegreenValueblueValueは変更したい画素値)。

img.at<cv::vec3b>(y, x)[0] = blueValue;
img.at<cv::vec3b>(y, x)[1] = greenValue;
img.at<cv::vec3b>(y, x)[2] = redValue;

Matクラスのatメソッドを呼び出して画素値を変更する方法

 以下に画素値を変更するサンプルコードを示します。

#include <opencv2/core.hpp>
#include <iostream>

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

    // (1)座標(0, 100)の画素値を変更する
    // atに渡すパラメーターは(y, x)の順である点に注意
    // Matのデータは(RGB表色系の場合)BGRの順に並んでいる点に注意
    img.at<cv::Vec3b>(100, 0)[0] = 255;
    img.at<cv::Vec3b>(100, 0)[1] = 0;
    img.at<cv::Vec3b>(100, 0)[2] = 0;

    // (2)座標(0, 100)の画素値を取得する
    cv::Vec3b intensity = img.at<cv::Vec3b>(100, 0);
    uchar blue  = intensity.val[0];
    uchar green = intensity.val[1];
    uchar red   = intensity.val[2];

    // (3)画素値を表示する
    std::cout << "R: " << (unsigned int)red   << std::endl;
    std::cout << "G: " << (unsigned int)green << std::endl;
    std::cout << "B: " << (unsigned int)blue  << std::endl;

    return 0;
}

画素値を変更するサンプルコード

 このサンプルコードを実行したときの標準出力は以下の通りです。この例では、(1)の処理で座標(0, 100)の画素値は青色R=0G=0B=255)に変更しているため、以下のような標準出力が行われます。

R: 0
G: 0
B: 255


上記のサンプルコードを実行したときの標準出力

       1|2 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。