cv::Point の使い方【OpenCV/C++】〜座標の型と基本操作〜
cv::Point は OpenCV で 2D 座標(x, y)を表す基本型です。circle や rectangle などの描画関数、ROI 指定、特徴点処理など、あらゆる場面で登場します。まず最小限の使い方を示します。
cv::Point pt(100, 200); // x=100, y=200
cv::circle(img, pt, 5, cv::Scalar(0, 255, 0), -1);
動作環境
- OpenCV 4.x
- コンパイル例:
g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4)
環境構築がまだの方は環境構築ガイドを先にどうぞ。
基本の使い方
cv::Point で座標を生成し、描画関数に渡すサンプルです。
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 500x500 の白画像を作成
cv::Mat img(500, 500, CV_8UC3, cv::Scalar(255, 255, 255));
// cv::Point の基本的な生成方法
cv::Point pt1(100, 150);
cv::Point pt2(400, 350);
// 座標値へのアクセス
std::cout << "pt1: x=" << pt1.x << ", y=" << pt1.y << std::endl;
// 2点間の差ベクトル(cv::Point は加減算をサポート)
cv::Point diff = pt2 - pt1;
std::cout << "diff: x=" << diff.x << ", y=" << diff.y << std::endl;
// 2点間の距離(norm はベクトルのノルムを返す)
double dist = cv::norm(pt2 - pt1);
std::cout << "distance: " << dist << std::endl;
// 描画関数に渡す
cv::circle(img, pt1, 10, cv::Scalar(255, 0, 0), -1); // 青い点
cv::circle(img, pt2, 10, cv::Scalar(0, 0, 255), -1); // 赤い点
cv::line(img, pt1, pt2, cv::Scalar(0, 0, 0), 2); // 2点を結ぶ線
cv::imshow("Point Demo", img);
cv::waitKey(0);
return 0;
}
実行結果:
pt1: x=100, y=150
pt2: x=400, y=350
diff: x=300, y=200
distance: 360.555
実行すると 500×500 の白画像ウィンドウが表示され、左上寄りに青い点、右下寄りに赤い点、両者を結ぶ黒い直線が描かれます。
コード解説
| 行 | 内容 |
|---|---|
cv::Point pt1(100, 150) |
x=100, y=150 の整数座標を生成 |
pt1.x / pt1.y |
メンバ変数で各軸の値を取得 |
pt2 - pt1 |
点同士の加減算。結果も cv::Point |
cv::norm(pt2 - pt1) |
ユークリッド距離を計算 |
cv::circle(img, pt1, ...) |
第2引数に cv::Point をそのまま渡せる |
引数と戻り値(型の種類)
cv::Point は実際にはテンプレートエイリアスです。精度に応じて使い分けます。
| 型名 | エイリアス | 要素型 | 主な用途 |
|---|---|---|---|
cv::Point |
cv::Point2i |
int |
描画・ROI などピクセル座標全般 |
cv::Point2f |
— | float |
特徴点・サブピクセル精度の座標 |
cv::Point2d |
— | double |
高精度なカメラ・幾何演算 |
cv::Point3i |
— | int |
3D 座標(整数) |
cv::Point3f |
— | float |
3D 座標(float) |
メンバ一覧(2D の場合)
| メンバ | 型 | 説明 |
|---|---|---|
.x |
T | X 座標 |
.y |
T | Y 座標 |
dot(pt) |
double | 内積 |
cross(pt) |
double | 外積(2D では Z 成分のスカラー) |
ddot(pt) |
double | 倍精度内積 |
inside(rect) |
bool | 矩形内にあるか判定 |
実践例
実践例 1: Point2f で特徴点を扱い、整数座標に変換して描画する
サブピクセル精度の座標を持つ Point2f は、描画関数に渡す前に Point へ明示的にキャストします。
#include <opencv2/opencv.hpp>
#include <vector>
int main()
{
cv::Mat img(400, 400, CV_8UC3, cv::Scalar(30, 30, 30));
// 浮動小数点精度の座標群(例: 特徴検出の結果を模擬)
std::vector<cv::Point2f> pts_f = {
{100.3f, 200.7f},
{250.1f, 150.9f},
{320.5f, 310.2f}
};
for (const auto& pf : pts_f) {
// Point2f → Point(int)へキャスト
cv::Point pi = static_cast<cv::Point>(pf);
cv::circle(img, pi, 6, cv::Scalar(0, 255, 255), 2);
// 座標テキストを描画
std::string label = "(" + std::to_string(static_cast<int>(pf.x))
+ "," + std::to_string(static_cast<int>(pf.y)) + ")";
cv::putText(img, label, pi + cv::Point(8, -8),
cv::FONT_HERSHEY_SIMPLEX, 0.45,
cv::Scalar(255, 255, 255), 1);
}
cv::imshow("Point2f Demo", img);
cv::waitKey(0);
return 0;
}
実行すると、暗い背景に黄色の丸が3つ描かれ、それぞれの横に座標ラベルが表示されます。
実践例 2: inside() で画像の範囲内チェック
処理前に座標が画像の範囲内かどうかを確認する典型パターンです。
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
cv::Mat img = cv::imread("input.jpg");
if (img.empty()) {
std::cerr << "画像を読み込めませんでした" << std::endl;
return 1;
}
// 画像サイズに対応した矩形
cv::Rect bounds(0, 0, img.cols, img.rows);
std::vector<cv::Point> pts = {
{100, 200},
{-5, 300}, // 範囲外(x が負)
{5000, 100} // 範囲外(x が大きすぎ)
};
for (const auto& pt : pts) {
if (pt.inside(bounds)) {
cv::circle(img, pt, 5, cv::Scalar(0, 255, 0), -1);
std::cout << pt << " -> 範囲内" << std::endl;
} else {
std::cout << pt << " -> 範囲外(スキップ)" << std::endl;
}
}
cv::imshow("Inside Check", img);
cv::waitKey(0);
return 0;
}
実行結果(画像サイズが 640×480 の場合):
[100, 200] -> 範囲内
[-5, 300] -> 範囲外(スキップ)
[5000, 100] -> 範囲外(スキップ)
cv::Point は operator<< を持つため std::cout にそのまま渡せます。範囲外座標を描画関数に渡すと assertion エラーや未定義動作につながるため、このチェックは実務で重要です。
つまずきポイント
⚠️ Point2f を描画関数に直接渡すとコンパイルエラーになる
cv::circle や cv::rectangle の座標引数は cv::Point(= Point2i)を期待します。Point2f を渡すと暗黙変換されずコンパイルエラーになります。
// NG: Point2f をそのまま渡す
cv::Point2f pf(100.5f, 200.3f);
cv::circle(img, pf, 5, cv::Scalar(255, 0, 0), -1); // コンパイルエラー
// OK: 明示的にキャスト
cv::circle(img, static_cast<cv::Point>(pf), 5, cv::Scalar(255, 0, 0), -1);
⚠️ Point の x, y は col, row(x が列方向・y が行方向)
cv::Mat のアクセスは mat.at<uchar>(row, col) と (行, 列) の順ですが、cv::Point は (x=col, y=row) の順です。Point と Mat::at を組み合わせるときに反転させてしまうバグが多発します。
cv::Point pt(col, row); // Point は (x=列, y=行)
uchar val = img.at<uchar>(pt.y, pt.x); // Mat::at は (行, 列) なので pt.y, pt.x の順
// img.at<uchar>(pt) と書くと内部で自動変換される(こちらが安全)
uchar val2 = img.at<uchar>(pt); // pt を直接渡すほうがミスが少ない
⚠️ 算術演算の型に注意
Point(int)と Point2f(float)を混在させた演算はコンパイルエラーになります。型を統一するか明示的にキャストしてください。
cv::Point pi(10, 20);
cv::Point2f pf(1.5f, 2.5f);
// auto result = pi + pf; // コンパイルエラー
auto result = cv::Point2f(pi) + pf; // OK: pi を Point2f に昇格
関連する関数
- cv::rectangle・circle・line の使い方【OpenCV/C++】 —
cv::Pointを引数に直接渡す描画関数群 - cv::putText の使い方【OpenCV/C++】 — テキスト描画の org 引数も
cv::Point - cv::Mat ROI で画像の一部を切り出す方法【OpenCV/C++】 —
cv::Rectの構築にcv::Pointを使う場面がある cv::Rect—cv::Point2点から矩形を作れる(cv::Rect(pt1, pt2))cv::Size— 幅・高さのペア。Pointと組み合わせてRectを構築することが多い
まとめ
cv::Pointは整数座標、cv::Point2fはサブピクセル精度と用途に応じて使い分ける。- 描画関数は
cv::Point(整数)を要求するため、Point2fからはstatic_cast<cv::Point>でキャストする。 inside()による範囲チェックを挟むことで、境界外アクセスによるクラッシュを防げる。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。

