cv::minMaxLoc の使い方【OpenCV/C++】〜最大値・最小値と位置を求める〜
cv::minMaxLoc は、cv::Mat 内の最小値・最大値とそれぞれの座標を一度に取得する関数です。輝度検査やテンプレートマッチングの結果解析など、画像処理の現場で頻繁に登場します。
最小限の呼び出し方は以下のとおりです。
double minVal, maxVal;
cv::Point minLoc, maxLoc;
cv::minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc);
動作環境
- OpenCV 4.x
- コンパイル例:
g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4)
環境構築がまだの方は環境構築ガイドを先にどうぞ。
基本の使い方
#include <iostream>
#include <opencv2/opencv.hpp>
int main()
{
// グレースケールで読み込む(minMaxLoc はシングルチャンネルが前提)
cv::Mat src = cv::imread("input.png", cv::IMREAD_GRAYSCALE);
if (src.empty()) {
std::cerr << "画像を読み込めませんでした" << std::endl;
return 1;
}
double minVal, maxVal;
cv::Point minLoc, maxLoc;
// 最小値・最大値とその座標を取得
cv::minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc);
std::cout << "最小値: " << minVal << " 座標: " << minLoc << std::endl;
std::cout << "最大値: " << maxVal << " 座標: " << maxLoc << std::endl;
return 0;
}
実行結果(例):
最小値: 3 座標: [42, 17]
最大値: 251 座標: [128, 64]
各行の解説
cv::IMREAD_GRAYSCALE—minMaxLocはシングルチャンネルcv::Matを要求するため、グレースケールで読み込むか、事前に変換が必要です。cv::minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc)— 5番目・6番目の引数にcv::Point*を渡すと座標も得られます。座標が不要ならnullptrを渡せます。- 結果の
cv::Pointは(x, y)=(列, 行)の順です。配列アクセスsrc.at<uchar>(maxLoc.y, maxLoc.x)と対応させる際に混同しやすいので注意してください。
引数と戻り値
| 引数 | 型 | 説明 |
|---|---|---|
src |
cv::InputArray |
入力配列。シングルチャンネルのみ対応 |
minVal |
double* |
最小値の格納先。不要なら nullptr |
maxVal |
double* |
最大値の格納先。不要なら nullptr |
minLoc |
cv::Point* |
最小値の座標の格納先。不要なら nullptr |
maxLoc |
cv::Point* |
最大値の座標の格納先。不要なら nullptr |
mask |
cv::InputArray |
処理対象領域を限定するマスク(省略可・デフォルト: cv::noArray()) |
戻り値: void
実践例
1. マスクを使って ROI 内の最大輝度点を探す
検査対象の領域だけを対象にしたい場合、マスクを活用します。
#include <iostream>
#include <opencv2/opencv.hpp>
int main()
{
cv::Mat src = cv::imread("input.png", cv::IMREAD_GRAYSCALE);
if (src.empty()) {
std::cerr << "画像を読み込めませんでした" << std::endl;
return 1;
}
// ROI 領域だけを有効にするマスクを作成
cv::Mat mask = cv::Mat::zeros(src.size(), CV_8UC1);
cv::Rect roi(50, 50, 200, 150);
mask(roi) = 255;
double minVal, maxVal;
cv::Point minLoc, maxLoc;
// マスク内だけで最小・最大を探索
cv::minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc, mask);
std::cout << "ROI内 最大値: " << maxVal << " 座標: " << maxLoc << std::endl;
// 最大値の点に円を描いて確認
cv::Mat disp;
cv::cvtColor(src, disp, cv::COLOR_GRAY2BGR);
cv::circle(disp, maxLoc, 8, cv::Scalar(0, 0, 255), 2);
cv::imwrite("result.png", disp);
return 0;
}
2. 差分画像の最大変化点を検出する
cv::absdiff で求めた差分画像に minMaxLoc を組み合わせると、フレーム間の最大変化点を素早く特定できます。
#include <iostream>
#include <opencv2/opencv.hpp>
int main()
{
cv::Mat frame1 = cv::imread("frame1.png", cv::IMREAD_GRAYSCALE);
cv::Mat frame2 = cv::imread("frame2.png", cv::IMREAD_GRAYSCALE);
if (frame1.empty() || frame2.empty()) {
std::cerr << "画像を読み込めませんでした" << std::endl;
return 1;
}
// 差分画像を生成
cv::Mat diff;
cv::absdiff(frame1, frame2, diff);
double minVal, maxVal;
cv::Point minLoc, maxLoc;
cv::minMaxLoc(diff, &minVal, &maxVal, &minLoc, &maxLoc);
std::cout << "最大差分値: " << maxVal << " 座標: " << maxLoc << std::endl;
// 最大変化点をマーキング
cv::Mat result;
cv::cvtColor(diff, result, cv::COLOR_GRAY2BGR);
cv::circle(result, maxLoc, 10, cv::Scalar(0, 255, 0), 2);
cv::imwrite("diff_result.png", result);
return 0;
}
maxVal がしきい値を超えている場合にアラートを出す、という検査ロジックに自然につながります。
つまずきポイント
⚠️ マルチチャンネル画像を渡すと assertion エラー
cv::minMaxLoc にカラー画像(CV_8UC3 等)をそのまま渡すと実行時に assertion が発生します。
OpenCV Error: Assertion failed (cn == 1) in minMaxLoc
cv::cvtColor でグレースケール変換するか、cv::split でチャンネルを分離してから渡してください。チャンネルごとの最大値が必要な場合は cv::minMaxIdx との組み合わせを検討します。
⚠️ Point の (x, y) と at(row, col) の軸が逆
maxLoc.x は列方向(横)、maxLoc.y は行方向(縦)です。ピクセル値を at で取り出す際は次のように書きます。
uchar val = src.at<uchar>(maxLoc.y, maxLoc.x); // 正しい順序
at<uchar>(maxLoc.x, maxLoc.y) と書くと、境界外アクセスやズレた画素を参照してしまいます。
⚠️ 浮動小数点 Mat での値のスケールに注意
CV_32F や CV_64F の cv::Mat(cv::normalize で [0.0, 1.0] に正規化した画像など)でも minMaxLoc は正しく動作しますが、CV_8U に変換した後に呼ぶと値が 0〜255 にスケールされている点を忘れがちです。検査値を数値として使う場合は変換前の Mat に対して呼ぶようにしましょう。
関連する関数
- cv::minMaxIdx —
cv::Matが多次元配列の場合に使用。座標をint[]配列で返します。 - cv::normalize — 最大・最小値を基準に正規化する際に
minMaxLocと組み合わせると便利です。 - cv::absdiff の使い方【OpenCV/C++】〜差分画像を作る〜 — 差分検査との組み合わせは実務でよく登場するパターンです。
- cv::add / addWeighted の使い方【OpenCV/C++】〜画像の加算・ブレンド合成〜 — 画素値操作の前後で最大・最小確認に使えます。
まとめ
cv::minMaxLoc はシングルチャンネルの cv::Mat に対して最小値・最大値とその座標を一度に返します。マスクを活用すれば ROI 内に絞った探索も簡単です。マルチチャンネル画像への誤適用と Point(x, y) の軸順だけ押さえておけば、実務での利用で困ることはほぼありません。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。
→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

