OpenCV/C++ rectangle・circle・line の使い方 〜図形を描画する〜

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

OpenCV/C++ rectangle・circle・line の使い方 〜図形を描画する〜

cv::rectanglecv::circlecv::line を使うと、cv::Mat 上に矩形・円・直線を1行で描画できます。いずれも描画先 Mat・座標・色(cv::Scalar)・線幅を引数に取る共通の設計です。

最小の呼び出し例(後述の完全プログラムで動作確認できます):

cv::rectangle(img, cv::Point(10, 20), cv::Point(200, 150), cv::Scalar(0, 255, 0), 2);
cv::circle(img, cv::Point(300, 300), 80, cv::Scalar(255, 0, 0), 3);
cv::line(img, cv::Point(0, 0), cv::Point(640, 480), cv::Scalar(0, 0, 255), 2);

動作環境

項目 バージョン
OpenCV 4.x
C++ 標準 C++17
g++ -std=c++17 main.cpp `pkg-config --cflags --libs opencv4` -o main
./main

基本の使い方

まず3つの関数をまとめて試せる完全プログラムを示します。入力画像がなくても動くよう、黒い Mat を生成してから描画しています。

#include <opencv2/opencv.hpp>

int main()
{
    // 480x640 の黒画像を生成(BGR 3チャンネル)
    cv::Mat img = cv::Mat::zeros(480, 640, CV_8UC3);

    // --- cv::rectangle ---
    // 左上 (50, 50) → 右下 (300, 200) に緑の矩形(線幅 2)
    cv::rectangle(img,
                  cv::Point(50, 50),
                  cv::Point(300, 200),
                  cv::Scalar(0, 255, 0),  // BGR: 緑
                  2);

    // cv::Rect を使った書き方(左上座標 + 幅・高さで指定)
    cv::Rect roi(350, 50, 200, 150);  // x, y, width, height
    cv::rectangle(img, roi, cv::Scalar(0, 200, 0), 2);

    // --- cv::circle ---
    // 中心 (160, 360)・半径 80 に青の円(線幅 3)
    cv::circle(img,
               cv::Point(160, 360),
               80,
               cv::Scalar(255, 0, 0),  // BGR: 青
               3);

    // thickness = -1 で塗りつぶし
    cv::circle(img, cv::Point(450, 360), 60, cv::Scalar(200, 100, 0), -1);

    // --- cv::line ---
    // 左上から右下への赤い直線(線幅 2)
    cv::line(img,
             cv::Point(0, 0),
             cv::Point(639, 479),
             cv::Scalar(0, 0, 255),  // BGR: 赤
             2);

    cv::imshow("shapes", img);
    cv::waitKey(0);
    return 0;
}

実行すると、黒背景に「緑の矩形 × 2・青の円(輪郭)・塗りつぶし円・赤い斜め線」が描かれたウィンドウが表示されます。

コードのポイント

  • cv::Mat::zeros(480, 640, CV_8UC3) — ゼロ埋め(黒)の Mat を生成。既存の画像に描く場合は cv::imread 後の Mat をそのまま渡せばよい。
  • cv::Scalar(B, G, R) — OpenCV の色指定は BGR順。RGB に慣れている場合は要注意。
  • cv::Rect(x, y, width, height)cv::rectanglecv::Rect も直接受け取れる。物体検出の結果ボックスを描くときに便利。
  • thickness = -1cv::circlecv::rectangle など共通で、負値を渡すと内部を塗りつぶす(cv::FILLED 定数も同義)。

引数と戻り値

cv::rectangle

引数 説明
img cv::InputOutputArray 描画先 Mat
pt1 cv::Point 左上頂点座標
pt2 cv::Point 右下頂点座標
color cv::Scalar 線の色(BGR)
thickness int 線幅。-1 または cv::FILLED で塗りつぶし
lineType int cv::LINE_8(デフォルト)/ cv::LINE_AA(アンチエイリアス)

cv::Rect を使うオーバーロードも存在します(pt1/pt2 の代わりに cv::Rect を1引数で渡す)。

cv::circle

引数 説明
img cv::InputOutputArray 描画先 Mat
center cv::Point 中心座標
radius int 半径(px)。直径ではない点に注意
color cv::Scalar 線の色(BGR)
thickness int 線幅。-1 で塗りつぶし
lineType int cv::LINE_8 / cv::LINE_AA

cv::line

引数 説明
img cv::InputOutputArray 描画先 Mat
pt1 cv::Point 始点座標
pt2 cv::Point 終点座標
color cv::Scalar 線の色(BGR)
thickness int 線幅
lineType int cv::LINE_8 / cv::LINE_AA

3関数とも戻り値は void です。


実践例

物体検出結果のバウンディングボックスを描画する

実務でよくあるユースケースです。検出器が返した std::vector<cv::Rect> をそのまま描画します。

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

int main()
{
    cv::Mat img = cv::imread("input.jpg");
    if (img.empty()) {
        std::cerr << "画像を読み込めませんでした" << std::endl;
        return 1;
    }

    // 検出結果を模擬(実際は検出器の出力が入る)
    std::vector<cv::Rect> detections = {
        cv::Rect(50,  30, 120, 180),
        cv::Rect(200, 80, 100, 140),
    };

    for (const auto& r : detections) {
        // バウンディングボックス(緑)
        cv::rectangle(img, r, cv::Scalar(0, 255, 0), 2);
        // 中心点に小さな円(赤)
        cv::Point center(r.x + r.width / 2, r.y + r.height / 2);
        cv::circle(img, center, 4, cv::Scalar(0, 0, 255), -1);
    }

    cv::imshow("result", img);
    cv::waitKey(0);
    return 0;
}

実行すると input.jpg に緑の矩形と中心点の赤丸が重畳表示されます。cv::Rect をそのまま cv::rectangle に渡せる点が実装を簡潔にします。


アンチエイリアスで滑らかな円を描く

デフォルトの cv::LINE_8 はジャギーが出ることがあります。表示品質が求められる場面では cv::LINE_AA を使います。

#include <opencv2/opencv.hpp>

int main()
{
    cv::Mat img = cv::Mat::zeros(300, 300, CV_8UC3);

    // LINE_8(デフォルト・ジャギーあり)
    cv::circle(img, cv::Point(80, 150), 60, cv::Scalar(255, 200, 0), 2, cv::LINE_8);

    // LINE_AA(アンチエイリアス・滑らか)
    cv::circle(img, cv::Point(220, 150), 60, cv::Scalar(255, 200, 0), 2, cv::LINE_AA);

    cv::imshow("aa_compare", img);
    cv::waitKey(0);
    return 0;
}

実行すると左右で描画品質の違いが確認できます。


つまずきポイント

⚠️ cv::Scalar の色順は BGR(RGB ではない)

cv::Scalar(255, 0, 0)  // 青(Blue=255)
cv::Scalar(0, 0, 255)  // 赤(Red=255)

OpenCV は内部的に BGR でデータを持つため、HTML/CSS の RGB 記法とは逆順です。「赤い矩形を描いたはずが青になった」はこのミスがほぼ全てです。


⚠️ imread が空 Mat を返す → 描画関数で assertion エラー

cv::Mat::zeros ではなく cv::imread を使うプログラムで、ファイルパスが存在しないと img.empty() == true のまま描画関数を呼びます。すると実行時に以下のような assertion エラーが発生します:

cv::error() : OpenCV(4.x) assertion failed (!_src.empty())

imread 直後に必ず empty() チェックを入れてください。

cv::Mat img = cv::imread("input.jpg");
if (img.empty()) { /* エラー処理 */ }

⚠️ cv::Rect が画像境界をはみ出すと assertion エラー

検出結果ボックスが画像サイズをわずかにはみ出すことがあります。cv::rectangle はそのまま渡すと実行時エラーになります。描画前にクリップ処理を入れましょう。

cv::Rect safe = r & cv::Rect(0, 0, img.cols, img.rows);
cv::rectangle(img, safe, cv::Scalar(0, 255, 0), 2);

& 演算子で2つの cv::Rect の共通領域(AND)を取れます。


関連する関数

  • cv::putText — テキスト描画。バウンディングボックスにラベルを付けるときに組み合わせて使う。
  • cv::arrowedLine — 矢印付き直線。cv::line と同じ引数体系。
  • cv::ellipse — 楕円描画。回転角・円弧範囲の指定ができる。
  • cv::fillPoly / cv::polylines — 多角形の塗りつぶし・輪郭描画。セグメンテーション結果の可視化に使う。

まとめ

  • cv::rectanglecv::circlecv::line はいずれも描画先 Mat・座標(cv::Point)・色(cv::Scalar の BGR 順)・線幅という共通の引数体系を持つ。
  • cv::Rect を直接 cv::rectangle に渡せるため、物体検出の結果ボックスの可視化がシンプルに書ける。
  • thickness = -1(または cv::FILLED)で塗りつぶし、lineType = cv::LINE_AA でアンチエイリアスと、細かい描画品質の調整も引数1つで対応できる。

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

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

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

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