cv::getTextSize の使い方【OpenCV/C++】〜描画する文字のサイズを測る〜

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

cv::getTextSize の使い方【OpenCV/C++】〜描画する文字のサイズを測る〜

cv::getTextSize は、cv::putText で描画する前に文字列の描画サイズ(幅・高さ)を取得する関数です。テキストを画像中央に配置したい、背景矩形をぴったり合わせたい、といった実務ユースケースで欠かせません。

int baseline = 0;
cv::Size textSize = cv::getTextSize("Hello", cv::FONT_HERSHEY_SIMPLEX, 1.0, 2, &baseline);

動作環境

  • OpenCV 4.x
  • C++17
  • ビルド: g++ -std=c++17 main.cpp \pkg-config –cflags –libs opencv4` -o main`

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


基本の使い方

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

int main()
{
    const std::string text    = "OpenCV C++";
    const int         font    = cv::FONT_HERSHEY_SIMPLEX;
    const double      scale   = 1.5;
    const int         thick   = 2;

    // ベースライン(文字の下端からデセンダー底までの距離)を受け取る変数
    int baseline = 0;

    // 文字列の描画サイズを取得
    cv::Size textSize = cv::getTextSize(text, font, scale, thick, &baseline);

    std::cout << "width   : " << textSize.width   << " px\n";
    std::cout << "height  : " << textSize.height  << " px\n";
    std::cout << "baseline: " << baseline          << " px\n";

    // 取得したサイズを使って画像中央にテキストを配置する
    cv::Mat img(300, 640, CV_8UC3, cv::Scalar(40, 40, 40));

    // 中央揃えの原点(putText の org はベースライン左端)
    cv::Point org(
        (img.cols - textSize.width)  / 2,
        (img.rows + textSize.height) / 2
    );

    // ベースラインを視覚確認用に描画(デバッグ時に便利)
    cv::line(img,
        cv::Point(0,          org.y + baseline),
        cv::Point(img.cols,   org.y + baseline),
        cv::Scalar(0, 255, 0), 1);

    cv::putText(img, text, org, font, scale, cv::Scalar(255, 255, 255), thick);

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

実行結果(コンソール出力例)

width   : 284 px
height  : 37  px
baseline: 11  px

実行すると、640×300 のダークグレー背景に “OpenCV C++” が中央揃えで表示され、ベースラインの位置に緑色のガイドラインが引かれたウィンドウが開きます。width / height の実際の値はフォント・スケール・太さによって変わります。

行ごとの解説

ポイント
int baseline = 0; ポインタで渡すので初期化しておく。nullptr を渡すとクラッシュする
cv::getTextSize(...) 戻り値 cv::Size に幅・高さが入る。ベースラインは引数経由
org.y の計算式 (rows + height) / 2 で垂直中央を求める。putText の y 座標はベースライン左端なので height を足す方向
cv::line(...) org.y + baseline がテキストの実際の底辺。ここにラインを引くとデバッグしやすい

引数と戻り値

cv::Size cv::getTextSize(
    const std::string& text,    // 計測したい文字列
    int    fontFace,            // フォント種別(cv::HersheyFonts)
    double fontScale,           // フォントスケール
    int    thickness,           // 線の太さ
    int*   baseLine             // [出力] ベースラインから文字底辺までのピクセル数
);
引数 説明
text const std::string& サイズを計測したい文字列
fontFace int cv::FONT_HERSHEY_SIMPLEX など cv::HersheyFonts の定数
fontScale double cv::putText と同じ値を渡す
thickness int cv::putText と同じ値を渡す
baseLine int* ベースラインから文字最下部までの距離(px)。nullptr 禁止
戻り値 cv::Size 文字列全体の幅(width)と高さ(height)(px)

⚠️ fontScalethicknesscv::putText に渡す値と必ず一致させてください。どちらか一方でも違うと、実際の描画と測定値がずれます。


実践例

1. テキストに背景矩形を重ねる(ラベル描画の定番パターン)

物体検出の結果ラベルなどでよく使われるパターンです。

#include <opencv2/opencv.hpp>

// テキスト付き背景矩形を描画するユーティリティ関数
void drawLabel(cv::Mat& img, const std::string& text, cv::Point topLeft,
               int font, double scale, int thick,
               cv::Scalar bgColor, cv::Scalar textColor)
{
    int baseline = 0;
    cv::Size ts  = cv::getTextSize(text, font, scale, thick, &baseline);

    // 背景矩形(パディング 4px)
    const int pad = 4;
    cv::rectangle(img,
        cv::Point(topLeft.x - pad, topLeft.y - ts.height - pad),
        cv::Point(topLeft.x + ts.width + pad, topLeft.y + baseline + pad),
        bgColor, cv::FILLED);

    // テキスト本体
    cv::putText(img, text, topLeft, font, scale, textColor, thick, cv::LINE_AA);
}

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

    drawLabel(img, "person  98%", cv::Point(50, 120),
              cv::FONT_HERSHEY_SIMPLEX, 0.8, 2,
              cv::Scalar(0, 128, 0), cv::Scalar(255, 255, 255));

    drawLabel(img, "car  75%", cv::Point(50, 220),
              cv::FONT_HERSHEY_SIMPLEX, 0.8, 2,
              cv::Scalar(200, 80, 0), cv::Scalar(255, 255, 255));

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

実行すると、”person 98%” と “car 75%” それぞれに背景色付きラベルが描画されたウィンドウが表示されます。パディング値を変えるだけで余白を自由に調整できます。

2. 複数行テキストの縦位置を自動計算する

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

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

    const int    font    = cv::FONT_HERSHEY_SIMPLEX;
    const double scale   = 0.7;
    const int    thick   = 1;
    const int    marginX = 20;
    const int    lineGap = 8; // 行間の余白

    std::vector<std::string> lines = {
        "OpenCV C++ Tips",
        "1. getTextSize で描画前にサイズを取得",
        "2. putText の org は左下ベースライン",
        "3. baseline を忘れると矩形がずれる",
    };

    int currentY = 50;
    for (const auto& line : lines) {
        int baseline = 0;
        cv::Size ts  = cv::getTextSize(line, font, scale, thick, &baseline);

        // 各行の高さを使って y 座標を積み上げる
        currentY += ts.height;
        cv::putText(img, line, cv::Point(marginX, currentY),
                    font, scale, cv::Scalar(220, 220, 220), thick, cv::LINE_AA);
        currentY += baseline + lineGap;
    }

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

実行すると、各行の高さを getTextSize で測りながら y 座標を積み上げていくため、スケールや内容が変わっても行間が自動的に適切に保たれます。


つまずきポイント

⚠️ baseLine に nullptr を渡すとクラッシュする

baseLine は必ず有効な int* を渡してください。ベースラインが不要な場合でも nullptr はNG です。

// NG: nullptr を渡すと実行時クラッシュ
cv::getTextSize(text, font, scale, thick, nullptr);

// OK: 使わなくても変数を用意して渡す
int baseline = 0;
cv::getTextSize(text, font, scale, thick, &baseline);

⚠️ fontScale / thickness を putText と揃えないとズレる

cv::getTextSize の計算は fontScalethickness に依存します。片方でも putText と異なる値を渡すと、実際の描画幅と測定値が食い違い、背景矩形やセンタリング位置がずれます。定数やパラメータ変数をひとつにまとめて両方に渡すのが安全です。

⚠️ putText の org の y 座標はベースラインであって上端ではない

cv::putText の第3引数 org文字列の左下ベースライン位置 です。「画像の y=0 から文字の上端まで何 px」ではありません。縦方向の中央揃えを計算するとき height を足す方向を間違えやすいので注意してください。

// 垂直中央揃えの正しい計算
int y = (img.rows + textSize.height) / 2;
// ← img.rows + height を 2 で割る(org が下端基準のため)

関連する関数

  • cv::putText — 実際にテキストを描画する関数。getTextSize とセットで使う
  • cv::rectangle — 背景矩形の描画に使用。実践例と組み合わせるのが定番
  • cv::line — ベースラインのデバッグ描画に便利

まとめ

cv::getTextSize を使えば、cv::putText で描画するテキストの幅・高さ・ベースラインを事前に取得できます。中央揃えや背景矩形との組み合わせで、テキスト描画まわりのレイアウトを正確に制御できます。baseLine ポインタと putText のパラメータ一致に気をつければ、ほぼすべての実務ケースに対応できます。

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

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

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

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