OpenCV/C++ rectangle・circle・line の使い方 〜図形を描画する〜
cv::rectangle・cv::circle・cv::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::rectangleはcv::Rectも直接受け取れる。物体検出の結果ボックスを描くときに便利。thickness = -1—cv::circle・cv::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::rectangle・cv::circle・cv::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)を開発しています。顔認証システムへの組み込み実績多数。

