cv::circle の使い方【OpenCV/C++】〜画像に円を描画する〜

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

cv::circle の使い方【OpenCV/C++】〜画像に円を描画する〜

cv::circlecv::Mat 上に円を描画する関数です。中心座標・半径・色・線幅を指定するだけで、輪郭円から塗りつぶし円まで1行で描けます。

先出し: 最小の呼び出し方は以下のとおりです。

cv::circle(img, cv::Point(cx, cy), radius, cv::Scalar(B, G, R), thickness);

動作環境

  • OpenCV 4.x
  • ビルド例: g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4) -o main

環境構築がまだの方は環境構築ガイドを先にどうぞ。


基本の使い方

以下は白地の画像に円を描画して保存する完全なサンプルです。

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

int main()
{
    // 500x500 の白背景画像を作成(BGR 3チャネル、値255で初期化)
    cv::Mat img(500, 500, CV_8UC3, cv::Scalar(255, 255, 255));

    // 輪郭円: 中心(250,250)・半径100・青・線幅3
    cv::circle(img, cv::Point(250, 250), 100, cv::Scalar(255, 0, 0), 3);

    // 塗りつぶし円: 中心(250,250)・半径40・赤・thickness=-1 で塗りつぶし
    cv::circle(img, cv::Point(250, 250), 40, cv::Scalar(0, 0, 255), -1);

    // 結果を保存
    if (!cv::imwrite("circle_output.png", img)) {
        std::cerr << "imwrite failed" << std::endl;
        return 1;
    }

    std::cout << "circle_output.png を保存しました" << std::endl;
    return 0;
}

実行結果:

circle_output.png を保存しました

circle_output.png を開くと、白地の中央に青い輪郭円と赤い塗りつぶし円が同心円状に描画されています。

コード解説

行の概要 ポイント
cv::Mat img(500, 500, CV_8UC3, ...) cv::Scalar(255,255,255) で白に初期化。画像がなくても即描画可能
cv::Point(250, 250) 中心座標。(x, y) の順(行列の row/col とは逆なので注意)
cv::Scalar(255, 0, 0) BGR 順。青=第1引数。RGB と逆なので注意
thickness = 3 正の整数で線幅(ピクセル)
thickness = -1 負値(cv::FILLED でも可)で塗りつぶし

引数と戻り値

void cv::circle(
    InputOutputArray  img,        // 描画先画像(8U または 浮動小数点型 Mat)
    Point             center,     // 円の中心座標
    int               radius,     // 半径(ピクセル)
    const Scalar&     color,      // 描画色(BGR)
    int               thickness = 1,        // 線幅。-1 または cv::FILLED で塗りつぶし
    int               lineType  = LINE_8,   // 線種(LINE_4 / LINE_8 / LINE_AA)
    int               shift     = 0         // 座標のビットシフト数(通常は 0)
);
引数 説明
img InputOutputArray 描画先。CV_8UC3 など通常の Mat
center cv::Point 円の中心(x, y)
radius int 半径(ピクセル)
color cv::Scalar BGR 色。グレースケール画像は Scalar(val)
thickness int 線幅。-1 / cv::FILLED で塗りつぶし
lineType int LINE_8(デフォルト)・LINE_AA(アンチエイリアス)など
shift int サブピクセル精度を使う場合の小数部ビット数。通常 0

戻り値は void です。

lineType の選択指針

  • LINE_8: デフォルト。高速。表示用途では十分
  • LINE_AA: アンチエイリアス付き。エッジが滑らか。UI表示・出力画像を人が見る場合に有効
  • LINE_4: 4連結。使う機会は少ない

実践例

実践例1: 検出した円をハイライト表示する

cv::HoughCircles などで得た円をそのまま描画する典型パターンです。

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

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

    cv::Mat gray;
    cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    cv::GaussianBlur(gray, gray, cv::Size(9, 9), 2.0);

    // ハフ変換で円を検出
    std::vector<cv::Vec3f> circles;
    cv::HoughCircles(gray, circles, cv::HOUGH_GRADIENT,
                     1.0,          // dp
                     gray.rows / 8,// minDist
                     200.0,        // param1
                     100.0,        // param2
                     10,           // minRadius
                     0);           // maxRadius(0=制限なし)

    // 検出した円を描画
    for (const auto& c : circles) {
        cv::Point center(cvRound(c[0]), cvRound(c[1]));
        int radius = cvRound(c[2]);

        // 中心点
        cv::circle(src, center, 3, cv::Scalar(0, 255, 0), -1, cv::LINE_AA);
        // 輪郭
        cv::circle(src, center, radius, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
    }

    std::cout << "検出した円の数: " << circles.size() << std::endl;

    if (!cv::imwrite("hough_result.png", src)) {
        std::cerr << "imwrite failed" << std::endl;
        return 1;
    }
    return 0;
}

実行すると、hough_result.png に検出円の輪郭(赤)と中心点(緑)が描画されます。coins.png は実際に用意した画像ファイルに置き換えてください。

画像の読み込みについては cv::imread の使い方【OpenCV/C++】も参考にしてください。


実践例2: 進捗メーターやアノテーション用の同心円マーカー

特定の点をマーキングするときに、中心+同心円を組み合わせると視認性が上がります。

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

int main()
{
    cv::Mat img(400, 400, CV_8UC3, cv::Scalar(30, 30, 30));

    cv::Point center(200, 200);

    // 同心円を複数描画
    for (int r = 20; r <= 160; r += 20) {
        // 半径に応じて色を変化させる(緑→赤のグラデーション的に)
        int g = static_cast<int>(255.0 * (160 - r) / 140);
        int rb = static_cast<int>(255.0 * r / 160);
        cv::circle(img, center, r, cv::Scalar(0, g, rb), 1, cv::LINE_AA);
    }

    // 中心に塗りつぶし円
    cv::circle(img, center, 6, cv::Scalar(255, 255, 255), -1, cv::LINE_AA);

    if (!cv::imwrite("concentric.png", img)) {
        std::cerr << "imwrite failed" << std::endl;
        return 1;
    }
    std::cout << "concentric.png を保存しました" << std::endl;
    return 0;
}

実行すると、濃いグレーの背景に同心円マーカーが描画された concentric.png が生成されます。

ファイルの保存については cv::imwrite の使い方【OpenCV/C++】を参照してください。


つまずきポイント

⚠️ 色の順序は BGR(RGB ではない)

OpenCV の cv::ScalarBlue, Green, Red の順です。「赤を指定したつもりが青になった」という誤りは頻出です。

cv::Scalar(0, 0, 255)   // 赤
cv::Scalar(255, 0, 0)   // 青
cv::Scalar(0, 255, 0)   // 緑

⚠️ thickness に 0 を指定すると何も描かれない

thickness = 0 は線幅ゼロなので描画されません。塗りつぶしたい場合は -1 または cv::FILLED を使ってください。値の取り違えで「描画されていない」と嵌まるケースがあります。

⚠️ グレースケール画像に BGR 3チャネルの色を指定するとアサーション失敗

CV_8UC1 の Mat に cv::Scalar(0, 0, 255) を渡すとアサーションエラーになります。グレースケール画像への描画は cv::Scalar(128) のように1値で指定するか、描画前に cv::cvtColor でカラーに変換してください。


関連する関数

  • cv::rectangle: 矩形を描画。cv::circle と同じ引数体系で使いやすい
  • cv::line: 2点間に直線を描画
  • cv::ellipse: 楕円・弧を描画。cv::circle の上位互換的な使い方も可能
  • cv::putText: 円に重ねてラベルを描く場合によく併用する

cv::rectanglecv::line との比較や組み合わせは OpenCV/C++ rectangle・circle・line の使い方 にまとめています。


まとめ

  • cv::circle は中心・半径・色・線幅を指定するだけで輪郭円・塗りつぶし円を1行で描ける
  • thickness = -1(または cv::FILLED)で塗りつぶし、lineType = LINE_AA でアンチエイリアスが有効になる
  • 色は BGR 順・グレースケール画像への描画時のチャネル不一致に注意

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

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

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

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