[C++] OpenCVの基本的な使い方

OpenCVは、コンピュータビジョンや画像処理のための強力なライブラリです。

[C++]でOpenCVを使用するには、まずライブラリをインストールし、#include <opencv2/opencv.hpp>をコードに追加します。

画像の読み込みにはcv::imread()、表示にはcv::imshow()、保存にはcv::imwrite()を使用します。

また、画像の変換やフィルタリングにはcv::cvtColor()cv::GaussianBlur()などの関数が利用可能です。

OpenCVを使うことで、画像処理の多くのタスクを効率的に実行できます。

この記事でわかること
  • OpenCVの概要と歴史、用途
  • 各プラットフォームでのOpenCVのインストール方法
  • 画像や動画の基本的な操作方法
  • OpenCVを用いた顔認識や物体追跡の実装方法
  • OpenCVのバージョンによる違いやパフォーマンス向上の方法

目次から探す

OpenCVとは何か

OpenCVの概要

OpenCV(Open Source Computer Vision Library)は、コンピュータビジョンや画像処理のためのオープンソースライブラリです。

C++をはじめ、PythonやJavaなどのプログラミング言語で利用可能で、リアルタイムの画像処理をサポートしています。

OpenCVは、画像の読み込み、加工、解析、そして機械学習を用いた高度な画像認識まで、幅広い機能を提供しています。

OpenCVの歴史と背景

OpenCVは、1999年にインテル社によって開発が始まりました。

初期の目的は、コンピュータビジョンの研究を促進し、商業アプリケーションの開発を支援することでした。

2000年に最初のリリースが行われ、その後も多くの研究者や開発者によって機能が拡張され続けています。

現在では、オープンソースコミュニティによって維持・開発されており、世界中の多くのプロジェクトで利用されています。

OpenCVの用途と利点

OpenCVは、以下のような用途で広く利用されています。

スクロールできます
用途説明
画像処理画像のフィルタリング、エッジ検出、色変換などの基本的な画像処理を行います。
コンピュータビジョン顔認識、物体検出、動作解析などの高度なビジョンタスクをサポートします。
機械学習画像データを用いた機械学習モデルのトレーニングと評価が可能です。

OpenCVの利点としては、以下の点が挙げられます。

  • オープンソース: 無料で利用でき、ソースコードが公開されているため、カスタマイズが容易です。
  • クロスプラットフォーム: Windows、macOS、Linuxなど、さまざまなプラットフォームで動作します。
  • 豊富な機能: 画像処理から機械学習まで、幅広い機能を一つのライブラリで利用できます。
  • コミュニティサポート: 世界中の開発者が参加する活発なコミュニティがあり、情報やサポートを得やすいです。

OpenCVは、これらの利点を活かして、研究開発から商業アプリケーションまで、さまざまな分野で活用されています。

OpenCVのインストール方法

OpenCVを利用するためには、まず開発環境にインストールする必要があります。

以下では、Windows、macOS、Linuxそれぞれのインストール方法を解説します。

Windowsでのインストール

OpenCVのダウンロードと展開

まず、OpenCVの公式サイトから必要なバージョンのOpenCVをダウンロードします。ダウンロードしたファイルは通常、ZIP形式で圧縮されています。

  1. ダウンロードしたZIPファイルを解凍します。
  2. 解凍後、以下のようなディレクトリ構成が生成されます:
  • opencv
    • build
    • source

ここで重要なのは、buildフォルダのみです。

sourceフォルダにはソースコードが含まれていますが、既にビルドされたライブラリを使用する場合は必要ありません。したがって、buildフォルダのみをプロジェクトに導入するために展開します。

1.2 環境変数の設定(オプション)

OpenCVのパスを環境変数として登録すると、プロジェクト設定が簡略化されます。

  1. Windowsのシステム設定から「環境変数」を開きます。
  2. ユーザー環境変数またはシステム環境変数に新しい変数OPENCVを追加し、その値にbuildフォルダへのパス(例: C:\opencv\build)を設定します。

この設定により、後のVisual Studioの設定で%OPENCV%という変数を使用できるようになります。

2. Visual Studioの設定

次に、Visual Studioを使用してOpenCVプロジェクトを設定します。

2.1 新しいプロジェクトの作成

  1. Visual Studioを起動し、「新しいプロジェクトの作成」を選択します。
  2. プロジェクトの設定はWindowsを対象としたC++プロジェクトなら基本的に何でも構いません

2.2 プロジェクトの構成設定

プロジェクトが作成されたら、次に構成設定を行います。

2.3 構成プロパティの設定

Visual Studioでプロジェクトのプロパティを設定します。

プロパティはソリューションエクスプローラーのプロジェクト名を右クリックし、[プロパティ]からアクセスできます。

2.3.1 デバッグ環境の設定
  1. 構成プロパティ > デバッグ を選択します。
  2. 環境 の項目に以下を設定します:
   PATH=%PATH%;%OPENCV%\build\x64\vc16\bin
2.3.2 VC++ディレクトリの設定
  1. 構成プロパティ > VC++ ディレクトリ に進みます。
  1. 以下の項目を設定します:
  • 外部インクルード ディレクトリ: %OPENCV%\build\include
  • ライブラリ ディレクトリ: %OPENCV%\build\x64\vc16\lib
2.3.3 リンカーの設定
  1. 構成プロパティ > リンカー > 入力 に進みます。
  2. 追加の依存ファイル の項目に以下を追加します:
  • opencv_world4100d.lib(Debugの場合)
  • opencv_world4100.lib(Releaseの場合)

これで、プロジェクトの設定が完了です。これらの設定により、Visual StudioでOpenCVを利用したC++開発が可能になります。

3. 実際のプロジェクトでの使用

設定が完了したら、実際のプロジェクトでOpenCVをインクルードし、使用することができます。例えば、次のようにコードを記述します:

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("path_to_image.jpg");
    if(image.empty()) {
        std::cout << "Could not open or find the image" << std::endl;
        return -1;
    }
    cv::imshow("Display window", image);
    cv::waitKey(0);
    return 0;
}

このコードを実行すると、指定した画像がウィンドウに表示されます。プロジェクト設定が正しく行われていれば、問題なく実行されるはずです。

macOSでのインストール

macOSでは、Homebrewを使用してOpenCVを簡単にインストールできます。

  1. Homebrewのインストール:
  • まだインストールしていない場合は、ターミナルで以下のコマンドを実行してHomebrewをインストールします。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. OpenCVのインストール:
  • ターミナルで以下のコマンドを実行してOpenCVをインストールします。
brew install opencv
  1. 環境変数の設定:
  • 必要に応じて、~/.bash_profileまたは~/.zshrcにOpenCVのパスを追加します。

Linuxでのインストール

Linuxでは、パッケージマネージャを使用してOpenCVをインストールすることができます。

以下はUbuntuでの例です。

  1. パッケージの更新:
  • ターミナルで以下のコマンドを実行してパッケージリストを更新します。
sudo apt update
  1. OpenCVのインストール:
  • 以下のコマンドを実行してOpenCVをインストールします。
sudo apt install libopencv-dev
  1. インストールの確認:
  • インストールが完了したら、以下のコマンドでインストールされたバージョンを確認します。
pkg-config --modversion opencv4

これらの手順を実行することで、各プラットフォームにOpenCVをインストールし、開発環境を整えることができます。

OpenCVの基本操作

OpenCVを使用すると、画像の読み込み、表示、保存、加工などの基本操作を簡単に行うことができます。

以下では、これらの基本操作について解説します。

画像の読み込みと表示

OpenCVでは、imread関数を使用して画像を読み込み、imshow関数で画像を表示します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // 画像が正しく読み込まれたか確認
    if (image.empty()) {
        std::cerr << "画像が見つかりません。" << std::endl;
        return -1;
    }
    // 画像を表示
    cv::imshow("Display Image", image);
    // キー入力を待つ
    cv::waitKey(0);
    return 0;
}

このコードは、指定したファイル名の画像を読み込み、ウィンドウに表示します。

cv::waitKey(0)は、キー入力があるまでウィンドウを保持します。

画像の保存

画像を保存するには、imwrite関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // 画像を保存
    cv::imwrite("output.jpg", image);
    return 0;
}

このコードは、読み込んだ画像をoutput.jpgという名前で保存します。

画像のサイズ変更

画像のサイズを変更するには、resize関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // サイズ変更後の画像を格納するためのMat
    cv::Mat resizedImage;
    // 画像のサイズを変更(幅100、高さ100に設定)
    cv::resize(image, resizedImage, cv::Size(100, 100));
    // 変更後の画像を表示
    cv::imshow("Resized Image", resizedImage);
    cv::waitKey(0);
    return 0;
}

このコードは、画像のサイズを100×100ピクセルに変更し、表示します。

画像の回転と反転

画像を回転させるには、rotate関数を使用し、反転させるにはflip関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // 回転後の画像を格納するためのMat
    cv::Mat rotatedImage;
    // 画像を90度回転
    cv::rotate(image, rotatedImage, cv::ROTATE_90_CLOCKWISE);
    // 反転後の画像を格納するためのMat
    cv::Mat flippedImage;
    // 画像を上下反転
    cv::flip(image, flippedImage, 0);
    // 回転した画像を表示
    cv::imshow("Rotated Image", rotatedImage);
    // 反転した画像を表示
    cv::imshow("Flipped Image", flippedImage);
    cv::waitKey(0);
    return 0;
}

このコードは、画像を90度回転させたものと上下反転させたものをそれぞれ表示します。

cv::ROTATE_90_CLOCKWISEは時計回りに90度回転を指定し、flipの第二引数0は上下反転を意味します。

画像処理の基本

OpenCVを使用すると、画像の基本的な処理を簡単に行うことができます。

ここでは、グレースケール変換、平滑化(ぼかし)、エッジ検出、二値化について解説します。

グレースケール変換

カラー画像をグレースケールに変換するには、cvtColor関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat colorImage = cv::imread("example.jpg");
    // グレースケール画像を格納するためのMat
    cv::Mat grayImage;
    // カラー画像をグレースケールに変換
    cv::cvtColor(colorImage, grayImage, cv::COLOR_BGR2GRAY);
    // グレースケール画像を表示
    cv::imshow("Grayscale Image", grayImage);
    cv::waitKey(0);
    return 0;
}

このコードは、カラー画像をグレースケールに変換し、表示します。

cv::COLOR_BGR2GRAYはBGRからグレースケールへの変換を指定します。

画像の平滑化(ぼかし)

画像を平滑化するには、GaussianBlur関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // 平滑化後の画像を格納するためのMat
    cv::Mat blurredImage;
    // 画像をガウシアンぼかしで平滑化
    cv::GaussianBlur(image, blurredImage, cv::Size(15, 15), 0);
    // 平滑化した画像を表示
    cv::imshow("Blurred Image", blurredImage);
    cv::waitKey(0);
    return 0;
}

このコードは、画像をガウシアンぼかしで平滑化し、表示します。

cv::Size(15, 15)はカーネルサイズを指定し、ぼかしの強さを調整します。

エッジ検出

エッジ検出には、Canny関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // グレースケール画像を格納するためのMat
    cv::Mat grayImage;
    cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
    // エッジ検出後の画像を格納するためのMat
    cv::Mat edges;
    // Canny法でエッジ検出
    cv::Canny(grayImage, edges, 100, 200);
    // エッジ検出した画像を表示
    cv::imshow("Edge Detected Image", edges);
    cv::waitKey(0);
    return 0;
}

このコードは、グレースケール画像に対してCanny法を用いてエッジを検出し、表示します。

100200はエッジ検出の閾値を指定します。

画像の二値化

画像を二値化するには、threshold関数を使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // グレースケール画像を格納するためのMat
    cv::Mat grayImage;
    cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
    // 二値化後の画像を格納するためのMat
    cv::Mat binaryImage;
    // 画像を二値化
    cv::threshold(grayImage, binaryImage, 128, 255, cv::THRESH_BINARY);
    // 二値化した画像を表示
    cv::imshow("Binary Image", binaryImage);
    cv::waitKey(0);
    return 0;
}

このコードは、グレースケール画像を閾値128で二値化し、表示します。

cv::THRESH_BINARYは二値化の方法を指定します。

動画処理の基本

OpenCVを使用すると、動画の読み込み、表示、フレームの抽出、処理、保存といった基本的な動画処理を行うことができます。

以下では、これらの基本操作について解説します。

動画の読み込みと表示

動画を読み込み、表示するには、VideoCaptureクラスを使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 動画ファイルを開く
    cv::VideoCapture cap("example.mp4");
    // 動画が開けない場合のエラーチェック
    if (!cap.isOpened()) {
        std::cerr << "動画ファイルが開けません。" << std::endl;
        return -1;
    }
    // フレームを格納するためのMat
    cv::Mat frame;
    // 動画の再生ループ
    while (true) {
        // フレームを取得
        cap >> frame;
        // フレームが空の場合、動画の終わり
        if (frame.empty()) {
            break;
        }
        // フレームを表示
        cv::imshow("Video", frame);
        // 30ミリ秒待機し、キー入力を確認
        if (cv::waitKey(30) >= 0) {
            break;
        }
    }
    return 0;
}

このコードは、指定した動画ファイルを読み込み、フレームごとに表示します。

cv::waitKey(30)は、30ミリ秒ごとに次のフレームを表示し、キー入力を待ちます。

フレームの抽出と処理

動画からフレームを抽出し、処理を行うことができます。

以下は、フレームをグレースケールに変換して表示する例です。

#include <opencv2/opencv.hpp>
int main() {
    // 動画ファイルを開く
    cv::VideoCapture cap("example.mp4");
    if (!cap.isOpened()) {
        std::cerr << "動画ファイルが開けません。" << std::endl;
        return -1;
    }
    cv::Mat frame, grayFrame;
    while (true) {
        cap >> frame;
        if (frame.empty()) {
            break;
        }
        // フレームをグレースケールに変換
        cv::cvtColor(frame, grayFrame, cv::COLOR_BGR2GRAY);
        // グレースケールフレームを表示
        cv::imshow("Grayscale Video", grayFrame);
        if (cv::waitKey(30) >= 0) {
            break;
        }
    }
    return 0;
}

このコードは、動画の各フレームをグレースケールに変換し、表示します。

動画の保存

処理した動画を保存するには、VideoWriterクラスを使用します。

#include <opencv2/opencv.hpp>
int main() {
    // 動画ファイルを開く
    cv::VideoCapture cap("example.mp4");
    if (!cap.isOpened()) {
        std::cerr << "動画ファイルが開けません。" << std::endl;
        return -1;
    }
    // 動画のフレームサイズを取得
    int frame_width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
    int frame_height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
    // 動画の保存設定
    cv::VideoWriter video("output.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 30, cv::Size(frame_width, frame_height));
    cv::Mat frame;
    while (true) {
        cap >> frame;
        if (frame.empty()) {
            break;
        }
        // フレームを保存
        video.write(frame);
        // フレームを表示
        cv::imshow("Video", frame);
        if (cv::waitKey(30) >= 0) {
            break;
        }
    }
    return 0;
}

このコードは、動画を読み込み、各フレームをそのまま保存し、新しい動画ファイルoutput.aviを作成します。

cv::VideoWriter::fourcc('M', 'J', 'P', 'G')は、保存する動画のコーデックを指定します。

OpenCVを用いた応用例

OpenCVは、基本的な画像処理だけでなく、さまざまな応用例に利用することができます。

ここでは、顔認識、物体追跡、画像フィルタリング、機械学習との連携について解説します。

顔認識の実装

OpenCVには、顔認識を行うためのHaar Cascade Classifierが組み込まれています。

これを使用して、画像や動画から顔を検出することができます。

#include <opencv2/opencv.hpp>
#include <opencv2/objdetect.hpp>
int main() {
    // 顔検出用のカスケード分類器の読み込み
    cv::CascadeClassifier face_cascade;
    face_cascade.load("haarcascade_frontalface_default.xml");
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // グレースケール画像に変換
    cv::Mat gray;
    cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
    // 顔を検出
    std::vector<cv::Rect> faces;
    face_cascade.detectMultiScale(gray, faces);
    // 検出した顔を矩形で囲む
    for (size_t i = 0; i < faces.size(); i++) {
        cv::rectangle(image, faces[i], cv::Scalar(255, 0, 0), 2);
    }
    // 結果を表示
    cv::imshow("Detected Faces", image);
    cv::waitKey(0);
    return 0;
}

このコードは、画像内の顔を検出し、矩形で囲んで表示します。

haarcascade_frontalface_default.xmlは、OpenCVの提供する顔検出用のカスケードファイルです。

物体追跡の実装

物体追跡には、OpenCVのTrackerクラスを使用します。

以下は、動画内の物体を追跡する例です。

#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
int main() {
    // 動画ファイルを開く
    cv::VideoCapture cap("example.mp4");
    if (!cap.isOpened()) {
        std::cerr << "動画ファイルが開けません。" << std::endl;
        return -1;
    }
    // 最初のフレームを取得
    cv::Mat frame;
    cap >> frame;
    // 追跡する物体の初期位置を選択
    cv::Rect2d bbox = cv::selectROI("Tracking", frame);
    // KCFトラッカーを作成
    cv::Ptr<cv::Tracker> tracker = cv::TrackerKCF::create();
    tracker->init(frame, bbox);
    while (cap.read(frame)) {
        // 物体を追跡
        tracker->update(frame, bbox);
        // 追跡した物体を矩形で囲む
        cv::rectangle(frame, bbox, cv::Scalar(255, 0, 0), 2);
        // 結果を表示
        cv::imshow("Tracking", frame);
        if (cv::waitKey(30) >= 0) {
            break;
        }
    }
    return 0;
}

このコードは、動画内の物体を追跡し、矩形で囲んで表示します。

cv::selectROIで追跡する物体の初期位置を選択します。

画像フィルタリングの応用

画像フィルタリングを応用して、特定の効果を画像に適用することができます。

以下は、画像にシャープ化フィルタを適用する例です。

#include <opencv2/opencv.hpp>
int main() {
    // 画像を読み込む
    cv::Mat image = cv::imread("example.jpg");
    // シャープ化フィルタのカーネル
    cv::Mat kernel = (cv::Mat_<float>(3, 3) <<
                      0, -1, 0,
                      -1, 5, -1,
                      0, -1, 0);
    // フィルタを適用
    cv::Mat sharpImage;
    cv::filter2D(image, sharpImage, -1, kernel);
    // 結果を表示
    cv::imshow("Sharpened Image", sharpImage);
    cv::waitKey(0);
    return 0;
}

このコードは、シャープ化フィルタを画像に適用し、エッジを強調した画像を表示します。

機械学習との連携

OpenCVは、機械学習ライブラリと連携して、画像データを用いたモデルのトレーニングや予測を行うことができます。

以下は、SVMを用いた簡単な分類の例です。

#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
int main() {
    // トレーニングデータとラベル
    cv::Mat trainingData = (cv::Mat_<float>(4, 2) << 1.0, 2.0, 2.0, 3.0, 3.0, 3.0, 4.0, 5.0);
    cv::Mat labels = (cv::Mat_<int>(4, 1) << 0, 0, 1, 1);
    // SVMの作成とトレーニング
    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
    svm->setType(cv::ml::SVM::C_SVC);
    svm->setKernel(cv::ml::SVM::LINEAR);
    svm->train(trainingData, cv::ml::ROW_SAMPLE, labels);
    // 新しいデータの予測
    cv::Mat sample = (cv::Mat_<float>(1, 2) << 2.5, 3.5);
    float response = svm->predict(sample);
    std::cout << "予測結果: " << response << std::endl;
    return 0;
}

このコードは、SVMを用いて簡単な2次元データの分類を行い、新しいデータのクラスを予測します。

cv::ml::SVMを使用してモデルを作成し、トレーニングデータで学習させます。

よくある質問

OpenCVのバージョンによる違いは?

OpenCVのバージョンによる違いは、主に新機能の追加、既存機能の改善、バグ修正、そしてAPIの変更などです。

メジャーバージョンアップでは、APIの互換性が失われることがあるため、コードの修正が必要になる場合があります。

例えば、OpenCV 3から4への移行では、いくつかの関数が非推奨となり、新しい関数が導入されました。

最新のバージョンを使用することで、より効率的で機能豊富なライブラリを活用できますが、プロジェクトの要件に応じて適切なバージョンを選択することが重要です。

OpenCVでサポートされている画像フォーマットは?

OpenCVは、以下のような多くの画像フォーマットをサポートしています。

  • JPEG
  • PNG
  • BMP
  • TIFF
  • WebP

これらのフォーマットは、imreadimwrite関数を使用して読み込みや保存が可能です。

特定のフォーマットを使用する場合は、OpenCVがそのフォーマットをサポートしているか確認することが重要です。

OpenCVのパフォーマンスを向上させる方法は?

OpenCVのパフォーマンスを向上させるためには、以下の方法があります。

  • マルチスレッド処理: OpenCVは、マルチスレッド処理をサポートしており、並列処理を活用することでパフォーマンスを向上させることができます。
  • GPUの活用: OpenCVはCUDAやOpenCLをサポートしており、GPUを活用することで計算速度を大幅に向上させることができます。
  • 最適化されたビルド: OpenCVをソースからビルドする際に、最適化オプションを有効にすることで、パフォーマンスを向上させることができます。

例えば、IntelのIPPやTBBを有効にすることが推奨されます。

まとめ

OpenCVは、画像処理やコンピュータビジョンの分野で広く利用されている強力なライブラリです。

この記事では、OpenCVの基本的な使い方から応用例までを解説しました。

これを機に、OpenCVを活用して、さまざまな画像処理プロジェクトに挑戦してみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • URLをコピーしました!
目次から探す