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) |
⚠️ fontScale と thickness は cv::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 の計算は fontScale と thickness に依存します。片方でも 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)を開発しています。顔認証システムへの組み込み実績多数。
