cv::Rect の使い方【OpenCV/C++】〜矩形領域を扱う基本型〜

OpenCV for C++
📌 準備: OpenCV の環境構築がまだの方はこちら → C++ 環境構築ガイドC#(OpenCvSharp)セットアップ

cv::Rect の使い方【OpenCV/C++】〜矩形領域を扱う基本型〜

cv::Rect は OpenCV で矩形領域を表す基本型です。左上座標 (x, y) と幅・高さ (width, height) の4つの値で矩形を定義し、ROI(関心領域)の切り出しや矩形描画など画像処理の至る所で使います。

最小の使い方はこれだけです。

cv::Rect roi(100, 50, 200, 150); // x, y, width, height
cv::Mat cropped = src(roi);      // ROI切り出し

動作環境

  • OpenCV 4.x
  • C++17
g++ -std=c++17 main.cpp `pkg-config --cflags --libs opencv4`

基本の使い方

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

int main()
{
    // 画像読み込み
    cv::Mat src = cv::imread("input.jpg");
    if (src.empty()) {
        std::cerr << "画像の読み込みに失敗しました" << std::endl;
        return -1;
    }

    // cv::Rect を定義: x=100, y=50, width=200, height=150
    cv::Rect roi(100, 50, 200, 150);

    // 矩形が画像範囲内に収まっているか確認
    cv::Rect imgRect(0, 0, src.cols, src.rows);
    cv::Rect safeRoi = roi & imgRect; // 画像領域との AND で安全な矩形を取得

    if (safeRoi.empty()) {
        std::cerr << "矩形が画像範囲外です" << std::endl;
        return -1;
    }

    // ROI 切り出し(コピーではなく参照)
    cv::Mat cropped = src(safeRoi);

    // 矩形を元画像に描画
    cv::rectangle(src, safeRoi, cv::Scalar(0, 255, 0), 2);

    // 各プロパティの確認
    std::cout << "x      : " << safeRoi.x      << std::endl;
    std::cout << "y      : " << safeRoi.y      << std::endl;
    std::cout << "width  : " << safeRoi.width  << std::endl;
    std::cout << "height : " << safeRoi.height << std::endl;
    std::cout << "面積   : " << safeRoi.area()  << std::endl;
    std::cout << "左上   : " << safeRoi.tl()    << std::endl;
    std::cout << "右下   : " << safeRoi.br()    << std::endl;

    cv::imwrite("output.jpg", src);
    cv::imwrite("cropped.jpg", cropped);

    return 0;
}

実行すると以下のように表示されます。

x      : 100
y      : 50
width  : 200
height : 150
面積   : 30000
左上   : [100, 50]
右下   : [300, 200]

行ごとの解説

行の内容 説明
cv::Rect roi(100, 50, 200, 150) (x, y, width, height) で矩形を定義
roi & imgRect & 演算子で2矩形の交差領域を取得(はみ出し防止に定番)
src(safeRoi) cv::Mat::operator()Rect を渡してROI参照を取得
safeRoi.tl() 左上座標を cv::Point で返す
safeRoi.br() 右下座標を cv::Point で返す(x+width, y+height
safeRoi.area() width * height を返す

引数と戻り値

cv::Rect はクラス(構造体)であり、複数のコンストラクタが用意されています。

コンストラクタ一覧

コンストラクタ 説明
Rect() 全ゼロで初期化
Rect(int x, int y, int width, int height) 最もよく使う形式
Rect(cv::Point pt, cv::Size sz) 左上座標とサイズで指定
Rect(cv::Point pt1, cv::Point pt2) 左上・右下の2点で指定

主なメンバと演算子

メンバ / 演算子 型 / 戻り値 説明
x, y int 左上座標
width, height int 幅・高さ
tl() cv::Point 左上座標
br() cv::Point 右下座標
area() int 面積 (width * height)
empty() bool width <= 0 または height <= 0 なら true
contains(cv::Point) bool 点が矩形内部にあるか
rect1 & rect2 cv::Rect 交差領域(AND)
rect1 \| rect2 cv::Rect 包含矩形(OR)
rect + point cv::Rect 矩形の平行移動
rect + size cv::Rect 矩形のサイズ変更

⚠️ br() が返す点は「右下の1つ外側」です。x + width, y + height と同値のため、ピクセルとして扱う場合は注意してください。


実践例

実践例1: 矩形同士の演算(AND / OR)

物体検出結果の重複判定や、複数領域の合算範囲を求めるときに使います。

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

int main()
{
    cv::Rect r1(50, 50, 200, 150);
    cv::Rect r2(100, 100, 200, 150);

    // 交差領域
    cv::Rect intersection = r1 & r2;
    std::cout << "交差領域: " << intersection << std::endl;

    // 包含矩形
    cv::Rect unionRect = r1 | r2;
    std::cout << "包含矩形: " << unionRect << std::endl;

    return 0;
}
交差領域: [150 x 100 from (100, 100)]
包含矩形: [250 x 200 from (50, 50)]

実践例2: Point・Size との変換

cv::Pointcv::Size と相互に組み合わせることで、動的な矩形生成が簡潔に書けます。

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

int main()
{
    cv::Point center(320, 240);
    cv::Size  halfSize(50, 50);

    // 中心点からパッチ矩形を生成
    cv::Rect patch(center - cv::Point(halfSize.width, halfSize.height),
                   cv::Size(halfSize.width * 2, halfSize.height * 2));

    std::cout << "パッチ矩形: " << patch << std::endl;

    // 矩形をオフセット移動
    cv::Rect shifted = patch + cv::Point(10, 20);
    std::cout << "移動後   : " << shifted << std::endl;

    return 0;
}
パッチ矩形: [100 x 100 from (270, 190)]
移動後   : [100 x 100 from (280, 210)]

つまずきポイント

⚠️ ROI が画像範囲をはみ出すと assertion エラー

src(roi) で範囲外の Rect を渡すと、実行時に cv::Exception が発生します。必ず roi & imgRect で画像範囲と AND を取ってから使うか、contains や範囲チェックを挟んでください。

cv::Rect safeRoi = roi & cv::Rect(0, 0, src.cols, src.rows);
if (!safeRoi.empty()) { ... }

⚠️ br() はピクセル座標ではなく「1つ外側」

br()(x + width, y + height) を返します。右下の「最後のピクセル」は (x + width - 1, y + height - 1) です。cv::rectangle に渡す場合は問題ありませんが、ループ境界などで間違えやすいです。

⚠️ ROI は参照コピー(ディープコピーではない)

cv::Mat cropped = src(roi);        // 参照(src のメモリを共有)
cv::Mat copied  = src(roi).clone(); // ディープコピー

src(roi) の結果はメモリを共有しています。ROI 画像を独立して加工したい場合は .clone() を忘れずに呼んでください。元画像を誤って書き換えるバグの原因になります。


関連する関数

  • cv::rectanglecv::Rect を渡して矩形を描画する
  • cv::Mat::operator()cv::Rect を使って ROI を切り出す
  • cv::Point — 左上・右下の座標を表す型。Rect と組み合わせて使う
  • cv::Size — 幅・高さを表す型。Rect のコンストラクタで使用
  • cv::boundingRect — 輪郭点群から cv::Rect を求める

まとめ

cv::Rect(x, y, width, height) で矩形を定義する OpenCV の基本型で、ROI 切り出し・描画・矩形演算など至る所で使います。ROI は参照コピーなので .clone() の要否を意識すること、範囲外アクセスを防ぐために & 演算子で安全な矩形を取得することが実装上のポイントです。

🛠 画像処理のプロが開発するSDK/API

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。

→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

タイトルとURLをコピーしました