cv::flip / cv::rotate の使い方【OpenCV/C++】〜画像の反転・90度回転〜
cv::flip は画像を上下・左右・両方向に反転し、cv::rotate は 90°単位で回転する関数です。前処理やデータ拡張、表示方向の補正など、実務でほぼ必ず使う場面があります。
最小構成はそれぞれ次のとおりです。
cv::flip(src, dst, 1); // 左右反転
cv::rotate(src, dst, cv::ROTATE_90_CLOCKWISE); // 時計回り 90°回転
動作環境
- OpenCV 4.x
- C++17
- ビルド例:
g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4)
環境構築がまだの方は環境構築ガイドを先にどうぞ。
基本の使い方
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 画像読み込み
cv::Mat src = cv::imread("input.png");
if (src.empty()) {
std::cerr << "画像の読み込みに失敗しました" << std::endl;
return -1;
}
cv::Mat flipped_h, flipped_v, flipped_both;
cv::Mat rot90cw, rot90ccw, rot180;
// ---- cv::flip ----
// flipCode > 0: 左右反転(Y軸基準)
cv::flip(src, flipped_h, 1);
// flipCode == 0: 上下反転(X軸基準)
cv::flip(src, flipped_v, 0);
// flipCode < 0: 上下+左右反転
cv::flip(src, flipped_both, -1);
// ---- cv::rotate ----
// 時計回り 90°
cv::rotate(src, rot90cw, cv::ROTATE_90_CLOCKWISE);
// 反時計回り 90°(= 時計回り 270°)
cv::rotate(src, rot90ccw, cv::ROTATE_90_COUNTERCLOCKWISE);
// 180°回転
cv::rotate(src, rot180, cv::ROTATE_180);
// 結果を保存
cv::imwrite("flipped_h.png", flipped_h);
cv::imwrite("flipped_v.png", flipped_v);
cv::imwrite("flipped_both.png", flipped_both);
cv::imwrite("rot90cw.png", rot90cw);
cv::imwrite("rot90ccw.png", rot90ccw);
cv::imwrite("rot180.png", rot180);
std::cout << "src サイズ: " << src.size() << std::endl;
std::cout << "rot90cw サイズ: " << rot90cw.size() << std::endl;
return 0;
}
実行結果
src サイズ: [640 x 480]
rot90cw サイズ: [480 x 640]
90° 回転すると幅と高さが入れ替わることが確認できます。cv::flip はサイズを変えず、cv::rotate の 90°/270° 回転はサイズが転置される点に注意してください。
引数と戻り値
cv::flip
void cv::flip(InputArray src, OutputArray dst, int flipCode);
| 引数 | 型 | 説明 |
|---|---|---|
src |
InputArray |
入力画像(チャンネル数・深度は任意) |
dst |
OutputArray |
出力画像(src と同サイズ・同型) |
flipCode |
int |
0: 上下反転 / > 0 (例: 1): 左右反転 / < 0 (例: -1): 両方向反転 |
戻り値: なし(void)
cv::rotate
void cv::rotate(InputArray src, OutputArray dst, int rotateCode);
| 引数 | 型 | 説明 |
|---|---|---|
src |
InputArray |
入力画像 |
dst |
OutputArray |
出力画像(90°/270° 時はサイズが転置) |
rotateCode |
int |
cv::ROTATE_90_CLOCKWISE / cv::ROTATE_90_COUNTERCLOCKWISE / cv::ROTATE_180 |
cv::rotate の定数一覧(OpenCV 4.x 時点):
| 定数 | 値 | 意味 |
|---|---|---|
cv::ROTATE_90_CLOCKWISE |
0 | 時計回り 90° |
cv::ROTATE_180 |
1 | 180° |
cv::ROTATE_90_COUNTERCLOCKWISE |
2 | 反時計回り 90° |
実践例
実践例 1: カメラ映像の上下反転(ミラー表示)
Webカメラや産業カメラの取り付け方向によっては、フレームを毎回反転させる必要があります。cv::flip はインプレース(src と dst を同一にする)にも対応しています。
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "カメラのオープンに失敗しました" << std::endl;
return -1;
}
cv::Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
// インプレースで左右反転(ミラー表示)
cv::flip(frame, frame, 1);
cv::imshow("Mirror", frame);
if (cv::waitKey(1) == 'q') break;
}
cv::destroyAllWindows();
return 0;
}
インプレース指定(src と dst が同じ Mat)は cv::flip では問題なく動作します。
実践例 2: データ拡張で 4 方向の反転画像を生成
学習データを水増しする典型パターンです。元画像 1 枚から 4 枚生成します。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <string>
int main()
{
cv::Mat src = cv::imread("input.png");
if (src.empty()) {
std::cerr << "画像の読み込みに失敗しました" << std::endl;
return -1;
}
// flipCode と保存ファイル名の対応テーブル
const std::vector<std::pair<int, std::string>> patterns = {
{ 1, "aug_lr.png" }, // 左右反転
{ 0, "aug_ud.png" }, // 上下反転
{ -1, "aug_both.png" }, // 両方向反転
};
// 元画像も含めて保存
cv::imwrite("aug_orig.png", src);
for (const auto& [code, filename] : patterns) {
cv::Mat dst;
cv::flip(src, dst, code);
cv::imwrite(filename, dst);
std::cout << filename << " を生成しました" << std::endl;
}
return 0;
}
実行すると次のように表示されます。
aug_lr.png を生成しました
aug_ud.png を生成しました
aug_both.png を生成しました
つまずきポイント
⚠️ flipCode の符号を混同しやすい
0 が上下、正数が左右、負数が両方向という対応は直感と逆に感じる場合があります。覚え方の目安として「軸番号」で考えると整理しやすいです。
flipCode == 0 → X軸(水平軸)を基準に折り返す → 上下反転
flipCode == 1 → Y軸(垂直軸)を基準に折り返す → 左右反転
flipCode == -1 → 両軸 → 上下+左右
コード中にマジックナンバーをそのまま書くと後から意味が分からなくなるため、コメントまたは名前付き定数を添えることを推奨します。
⚠️ cv::rotate は 90°単位の整数回転しかできない
任意角度の回転には cv::warpAffine を使う必要があります。cv::rotate に整数以外の回転角を渡すことはできず、rotateCode には定数値(0/1/2)以外を渡しても定義された動作になりません。45° 回転などを実装したい場合は cv::warpAffine を選んでください。
⚠️ 90°回転後のサイズを前提にした処理でクラッシュする
cv::rotate で 90° や 270° 回転した Mat は幅と高さが入れ替わります。その後の処理(ROI 切り出しや他画像との演算など)で元のサイズを前提にしているとアサーションエラーが発生します。回転後は必ず dst.size() を確認し、後続処理のサイズを合わせてください。
// ⚠️ rot90cw は縦横が反転しているのに src と同サイズで ROI を取ると assertion エラー
cv::Rect roi(0, 0, src.cols, src.rows); // NG: rot90cw ではオーバー
cv::Mat cropped = rot90cw(roi);
関連する関数
- cv::transpose — 行列の転置(対角線を基準に反転)。
cv::flip+cv::transposeの組み合わせで任意方向の 90° 回転を再現できます。cv::rotateはその組み合わせのショートカット関数です - cv::warpAffine — アフィン変換による任意角度の回転。
cv::rotateが対応しない角度が必要なときはこちらを使います - cv::copyMakeBorder の使い方【OpenCV/C++】〜画像に枠(パディング)を付ける〜 — 回転後の余白処理と組み合わせることがあります
- cv::add / addWeighted の使い方【OpenCV/C++】〜画像の加算・ブレンド合成〜 — 反転画像を合成する場面で併用します
まとめ
cv::flipはflipCodeで上下・左右・両方向の反転を1関数でカバーし、インプレースにも対応します。cv::rotateはROTATE_90_CLOCKWISEなどの定数で 90° 単位の回転を簡潔に記述できます。- 90°/270° 回転後はサイズが転置されるため、後続処理のサイズ前提に注意してください。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。
→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

