cv::Scalar の使い方【OpenCV/C++】〜色・スカラー値の型を完全解説〜

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

cv::Scalar の使い方【OpenCV/C++】〜色・スカラー値の型を完全解説〜

cv::Scalar は OpenCV で色や数値をまとめて渡すための基本型です。cv::rectanglecv::circle に色を指定するとき、cv::Mat::setTo で画像を塗りつぶすとき、どこにでも登場します。

最小の使い方はこうです。

cv::Scalar blue(255, 0, 0);       // BGR 順: Blue=255
cv::Scalar white(255, 255, 255);  // グレースケール・カラー共通

動作環境

  • OpenCV 4.x(4.5 以降推奨)
  • C++17
  • ビルド例:
g++ -std=c++17 main.cpp `pkg-config --cflags --libs opencv4` -o main

基本の使い方

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

int main()
{
    // --- 1. Scalar の初期化 ---
    cv::Scalar gray(128);                    // 1チャンネル: 輝度128
    cv::Scalar bgr(255, 0, 0);              // 3チャンネル: 青
    cv::Scalar bgra(0, 255, 0, 128);        // 4チャンネル: 緑+アルファ128

    // --- 2. 要素へのアクセス ---
    std::cout << "B=" << bgr[0]
              << " G=" << bgr[1]
              << " R=" << bgr[2] << std::endl;

    // --- 3. Mat を Scalar で塗りつぶす ---
    cv::Mat img(300, 400, CV_8UC3);
    img.setTo(cv::Scalar(200, 200, 200)); // 明るいグレーで初期化

    // --- 4. 図形描画に使う ---
    cv::rectangle(img,
                  cv::Point(50, 50), cv::Point(350, 250),
                  cv::Scalar(0, 0, 255),  // 赤
                  3);                      // 線幅3px

    cv::circle(img,
               cv::Point(200, 150), 80,
               cv::Scalar(255, 128, 0),  // 水色
               cv::FILLED);

    // --- 5. 結果確認(ファイル保存) ---
    if (!cv::imwrite("output.png", img)) {
        std::cerr << "保存失敗" << std::endl;
        return 1;
    }
    std::cout << "output.png を保存しました" << std::endl;
    return 0;
}

実行結果:

B=255 G=0 R=0
output.png を保存しました

output.png を開くと、明るいグレーの背景に赤い矩形と水色の塗りつぶし円が描かれた 400×300 の画像が確認できます。

各処理の解説

内容
cv::Scalar gray(128) 要素1つだけ渡すと残り3つは自動で 0 になる
bgr[0] 添字アクセスで各チャンネルを取得。型は double
img.setTo(cv::Scalar(...)) Mat 全画素を指定値で上書き。チャンネル数を揃える必要あり
cv::Scalar(0, 0, 255) OpenCV は BGR 順。RGB と R/B が逆なので注意
cv::Scalar(255, 128, 0) 引数は double で渡し、描画時に uchar へ変換される

引数と戻り値

cv::Scalarcv::Scalar_<double> の typedef です。コンストラクタは以下の通りです。

コンストラクタ 説明
Scalar() 全要素 0.0 で初期化
Scalar(double v0) [v0, 0, 0, 0]
Scalar(double v0, double v1, double v2=0, double v3=0) 最大4要素まで指定
Scalar::all(double v) 全要素を同じ値で初期化する静的メソッド

要素は内部的に double val[4] に格納されます。添字 [0][3] で読み書き可能です。

よく使うファクトリ

cv::Scalar::all(0)    // 全チャンネルをゼロに(黒・消去用)
cv::Scalar::all(255)  // 全チャンネルを255に(白・マスク用)

実践例

1. チャンネル数に合わせて Scalar を切り替える

グレースケール画像とカラー画像の両方に対応した描画関数を書く場合、チャンネル数で Scalar を分岐させます。

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

// 画像のチャンネル数に合った「白」を返す
cv::Scalar makeWhite(const cv::Mat& img)
{
    if (img.channels() == 1) {
        return cv::Scalar(255);
    } else {
        return cv::Scalar(255, 255, 255);
    }
}

int main()
{
    cv::Mat gray(200, 200, CV_8UC1, cv::Scalar(0));
    cv::Mat color(200, 200, CV_8UC3, cv::Scalar(0, 0, 0));

    // 両方に同じロジックで白矩形を描画
    cv::rectangle(gray,  cv::Point(20, 20), cv::Point(180, 180), makeWhite(gray),  2);
    cv::rectangle(color, cv::Point(20, 20), cv::Point(180, 180), makeWhite(color), 2);

    cv::imwrite("gray_rect.png",  gray);
    cv::imwrite("color_rect.png", color);
    std::cout << "gray_rect.png / color_rect.png を保存しました" << std::endl;
    return 0;
}

実行すると、gray_rect.png には白い矩形枠が、color_rect.png にも同様の白い矩形枠が描かれた画像が保存されます。


2. Mat の特定チャンネルを Scalar で取得する

cv::mean の戻り値は cv::Scalar です。4チャンネル分の平均輝度が一度に取得できます。

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

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

    // 画像全体の BGR 各チャンネル平均
    cv::Scalar meanVal = cv::mean(img);
    std::cout << "平均 B=" << meanVal[0]
              << " G=" << meanVal[1]
              << " R=" << meanVal[2] << std::endl;
    return 0;
}

実行すると、各チャンネルの平均輝度が以下のように出力されます。

平均 B=112.4 G=98.7 R=87.2

(数値は画像によって異なります)


つまずきポイント

⚠️ BGR と RGB の順序を間違える

OpenCV は BGR 順です。cv::Scalar(255, 0, 0) は赤ではなく青です。Web や他のライブラリから色コードを持ってくるときは必ず R と B を入れ替えてください。

// HTML #FF0000(赤)を OpenCV に渡す場合
cv::Scalar red(0, 0, 255);   // ✅ BGR 順
cv::Scalar red(255, 0, 0);   // ❌ これは青になる

⚠️ チャンネル数の不一致で assertion が発生する

CV_8UC1 の Mat に cv::Scalar(255, 255, 255)setTo しても動作はしますが、cv::linecv::rectangle の描画では内部チェックが走り、デバッグビルドで assertion が出ることがあります。チャンネル数に合った Scalar を渡すのが安全です。

⚠️ Scalar の要素型は double

cv::Scalar の内部型は double です。CV_8UC3 の Mat に使う場合、最終的に uchar(0〜255)にクランプされます。256-1 を渡しても assertion にはなりませんが、意図しない色になります。

cv::Scalar s(300, -10, 128);
// CV_8UC3 に setTo すると → [255, 0, 128] に飽和する

関連する関数

  • cv::mean — 画像の平均値を cv::Scalar で返す
  • cv::sum — 画素値の合計を cv::Scalar で返す
  • cv::rectangle / cv::circle / cv::linecv::Scalar で色を指定する描画関数
  • cv::Mat::setTo — Mat 全体を cv::Scalar 値で塗りつぶす

まとめ

cv::Scalar は OpenCV の色・数値指定の基本型で、最大4チャンネルの double 値を保持します。OpenCV は BGR 順であること、内部型が double であることを押さえておけば、描画・初期化・統計関数のどこでも迷わず使えます。

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

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

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

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