Cv2.GetRotationMatrix2D の使い方【OpenCV/C#(OpenCvSharp)】〜回転行列を作る〜

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

Cv2.GetRotationMatrix2D の使い方【OpenCV/C#(OpenCvSharp)】〜回転行列を作る〜

Cv2.GetRotationMatrix2D は、指定した中心点・回転角度・スケールから 2×3 のアフィン変換行列(回転行列) を生成する関数です。生成した行列を Cv2.WarpAffine に渡すことで、任意の点を中心に画像を回転できます。

最小構成のコードは次のとおりです。

Mat rotMat = Cv2.GetRotationMatrix2D(center, angle, scale);
Cv2.WarpAffine(src, dst, rotMat, src.Size());

動作環境

  • OpenCV 4.x(OpenCvSharp4 / OpenCvSharp4.runtime.win)
  • .NET 8 コンソールアプリ(Windows)

NuGet で以下の2パッケージを追加してください。

dotnet add package OpenCvSharp4
dotnet add package OpenCvSharp4.runtime.win

環境構築がまだの方は環境構築ガイドを先にどうぞ。

基本の使い方

using OpenCvSharp;

// 入力画像を読み込む
using Mat src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像を読み込めませんでした");

// 回転の基準となる中心点(画像の中央)
Point2f center = new Point2f(src.Width / 2f, src.Height / 2f);

// 回転角度(度): 正値で反時計回り、負値で時計回り
double angle = 45.0;

// スケール: 1.0 で等倍
double scale = 1.0;

// 2×3 の回転行列を生成
using Mat rotMat = Cv2.GetRotationMatrix2D(center, angle, scale);

// 回転行列を使ってアフィン変換を適用
using Mat dst = new Mat();
Cv2.WarpAffine(src, dst, rotMat, src.Size());

// 結果を保存・表示
Cv2.ImWrite("output_rotated.jpg", dst);
Cv2.ImShow("Rotated", dst);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();

実行結果

input.jpg が画像中心を基準に 45 度回転した画像として output_rotated.jpg に保存されます。
ウィンドウに回転後の画像が表示されます。

コード解説

行 説明
ImRead 入力画像を読み込む
Point2f center 回転の中心座標。画像中央にするには Width/2, Height/2 を渡す
angle = 45.0 反時計回りに 45 度回転。時計回りにしたい場合は -45.0
scale = 1.0 等倍。0.5 で半分、2.0 で2倍にしながら回転できる
GetRotationMatrix2D 2×3 の Mat(CV_64F)を返す
WarpAffine 生成した行列を実際の画像変換に適用する

引数と戻り値

Mat Cv2.GetRotationMatrix2D(Point2f center, double angle, double scale)
引数 型 説明
center Point2f 回転中心座標(ピクセル単位の浮動小数点)
angle double 回転角度(度)。正値 = 反時計回り
scale double 等方スケール係数。1.0 で等倍
戻り値 型 説明
回転行列 Mat(2×3, CV_64F) WarpAffine にそのまま渡せる

⚠️ 戻り値の Mat は IDisposable です。必ず using で解放してください。

実践例

① 回転後に画像が切れないようキャンバスを拡張する

デフォルトの WarpAffine は出力サイズが入力と同じため、回転で画像の角が切れることがあります。出力サイズを斜辺の長さに合わせると全体が収まります。

using OpenCvSharp;

using Mat src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像を読み込めませんでした");

double angle = 30.0;
double scale = 1.0;

// 対角線の長さを新しいキャンバスサイズにする
int diagLen = (int)Math.Ceiling(Math.Sqrt(src.Width * src.Width + src.Height * src.Height));
Size newSize = new Size(diagLen, diagLen);

// 新しいキャンバスの中心を回転中心にする
Point2f center = new Point2f(diagLen / 2f, diagLen / 2f);

// 元画像を新キャンバスの中央に配置するためのオフセット
int offsetX = (diagLen - src.Width) / 2;
int offsetY = (diagLen - src.Height) / 2;

// 黒背景のキャンバスを作成して元画像をコピー
using Mat canvas = Mat.Zeros(newSize, src.Type());
src.CopyTo(canvas[new Rect(offsetX, offsetY, src.Width, src.Height)]);

// 回転行列を生成してアフィン変換
using Mat rotMat = Cv2.GetRotationMatrix2D(center, angle, scale);
using Mat dst = new Mat();
Cv2.WarpAffine(canvas, dst, rotMat, newSize);

Cv2.ImWrite("output_no_crop.jpg", dst);
Console.WriteLine($"出力サイズ: {dst.Width} x {dst.Height}");

② ループで連続回転アニメーション(フレーム生成)

using OpenCvSharp;

using Mat src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像を読み込めませんでした");

Point2f center = new Point2f(src.Width / 2f, src.Height / 2f);

// 0〜359 度を 10 度刻みで回転したフレームを保存
for (int deg = 0; deg < 360; deg += 10)
{
    using Mat rotMat = Cv2.GetRotationMatrix2D(center, deg, 1.0);
    using Mat frame = new Mat();
    Cv2.WarpAffine(src, frame, rotMat, src.Size());
    Cv2.ImWrite($"frame_{deg:D3}.jpg", frame);
}

Console.WriteLine("全フレームを保存しました");

つまずきポイント

⚠️ 戻り値の Mat を using で解放しないとメモリリークする

GetRotationMatrix2D の戻り値はネイティブヒープ上の Mat オブジェクトです。C# の GC は OpenCV のネイティブメモリを管理しないため、using による明示的解放が必須です。ループ内で繰り返し呼ぶ実践例②では特に注意してください。

// NG: 解放されない
Mat rotMat = Cv2.GetRotationMatrix2D(center, angle, 1.0);

// OK: using で確実に解放
using Mat rotMat = Cv2.GetRotationMatrix2D(center, angle, 1.0);

⚠️ 角度の回転方向に注意(OpenCV は Y 軸が下向き)

OpenCV の座標系は Y 軸が下向き のため、angle の正値が 反時計回り に見えます(数学の標準座標系とは逆)。時計回りに回転させたい場合は負の角度を渡してください。

// 時計回りに 45 度回転
using Mat rotMat = Cv2.GetRotationMatrix2D(center, -45.0, 1.0);

⚠️ GetRotationMatrix2D だけでは画像は変わらない

GetRotationMatrix2D は行列を生成するだけで、画像への適用は Cv2.WarpAffine で行います。生成した行列を渡し忘れると元画像のままになります。セットで使うことを意識してください。

関連する関数

  • Cv2.WarpAffine — GetRotationMatrix2D で作った行列を受け取り、実際にピクセルを変換する関数。セットで使う
  • Cv2.GetAffineTransform — 3点対応からアフィン行列を求める関数。回転以外の変形も扱える
  • Cv2.WarpPerspective — 4点対応からホモグラフィ変換を行う関数。透視変換が必要な場合に使用

まとめ

Cv2.GetRotationMatrix2D は中心・角度・スケールを指定するだけで回転行列を生成できる便利な関数です。戻り値の Mat は必ず using で解放し、実際の変換は Cv2.WarpAffine とセットで行いましょう。画像が切れる場合はキャンバスサイズを対角線長に合わせる実践例①のテクニックが有効です。

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

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。

→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

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