format_list_bulleted
【C++/OpenCV】画像の回転、拡大、縮小の実装について解説
最終更新日時:2020-11-07 02:32:18



本記事では、画像の回転のやり方を2種類紹介し、拡大、縮小についてC++とOpenCVを用いたプログラムで解説します。

前提知識

C++とOpenCVを用いた画像の読み込み、表示を理解していることが前提となっている記事です。理解してなければ、以下の記事を参照しましょう。

画像の回転やり方について(その1:90度回転)

はじめに画像の回転ができるソースコードを紹介して、そのソースコードをもとに解説していきます。(画像の読み込みや出力については省かせていただきます。)

説明に用いるソースコード

タイトル:ファイル構造

├ kaiten.cpp
└  opencv-logo.png

タイトル:kaiten.cpp

#include<iostream>
#include<cmath>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
   	// 画像を格納するオブジェクトを宣言して画像を読み込む
	cv::Mat	image = cv::imread("./opencv-logo.png");;
 	//エラー処理
	if (image.empty() == true) {
		// 画像の中身が空なら終了する
		return 0;
	}
    //回転
    cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE); //時計回りに90度回転
    // cv::rotate(image, image, cv::ROTATE_180); //180度回転
    // cv::rotate(image, image, cv::ROTATE_90_COUNTERCLOCKWISE); //時計回りに270度回転

	// ウィンドウに画像を表示する
	cv::imshow("opencv_logo", image);
	// キーが押されるまで待つ
	cv::waitKey(0);
	//  画像を書き出し
	cv::imwrite("output.png", image);	
 
    return 0;
}

画像の回転

画像を90度ずつ回転するには以下のcv::rotateを使用します。第1引数に元の画像、第2引数に回転後の画像、第3引数に90、180、270のどの角度で回転させるかを設定します。また、第3引数には以下の表を参照してください。

cv::rotate(元の画像,回転後の画像 ,オプション );
オプション回転角度(時計回り)
cv::ROTATE_90_CLOCKWISE
90度
cv::ROTATE_180
180度
cv::ROTATE_90_COUNTERCLOCKWISE
270度

実装

以下のコマンドでコンパイルを行い、実行します。

$ g++ -std=c++11 -o kaiten kaiten.cpp `pkg-config --cflags --libs opencv4 `
$ ./kaiten

cv::rotateのオプションを3種類それぞれ行なった結果が以下の通りです。

cv::ROTATE_90_CLOCKWISE

(90度回転)

cv::ROTATE_180

(180度回転)

cv::ROTATE_90_COUNTERCLOCKWISE

(270度回転)

ROTATE_90_CLOCKWISE

cv::ROTATE_180

90_COUNTERCLOCKWISE


画像の回転・拡大・縮小のやり方について(その2:90度だけでなく細かく回転する方法)

今度は90度回転だけでなく、細かい角度での回転方法を説明します。また、その中で画像の拡大・縮小についても含め説明します。


説明に用いるソースコード

タイトル:ファイル構造

├ kaiten.cpp
└  opencv-logo.png


タイトル:kaiten_syukusyou.cpp

#include<iostream>
#include<cmath>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
   	// 画像を格納するオブジェクトを宣言して画像を読み込む
	cv::Mat	image = cv::imread("./input/image/opencv-logo.png");;
 	//エラー処理
	if (image.empty() == true) {
		// 画像の中身が空なら終了する
		return 0;
	}
    float width = image.cols;
    float height = image.rows;
    
    cv::Point2f center = cv::Point2f((width / 2),(height / 2));//図形の中心
    double degree = 45.0;  // 回転角度
    double scale = 0.5; //大きさの定義

    cv::Mat change = cv::getRotationMatrix2D(center, degree, scale); //回転&拡大縮小
    cv::warpAffine(image, image, change, image.size(), cv::INTER_CUBIC,cv::BORDER_CONSTANT,cv::Scalar(0, 0, 0)); //画像の変換(アフィン変換)

	// ウィンドウに画像を表示する
	cv::imshow("opencv_logo", image);
	// キーが押されるまで待つ
	cv::waitKey(0);
	//  画像を書き出し
	cv::imwrite("output.png", image);	
 
    return 0;
}

ソースコードの解説

この方法についてはソースコードを分解して解説していきます。

タイトル:kaiten_syukusyou1.cpp

    float width = image.cols; //横幅の取得
    float height = image.rows; //高さの取得
    
    cv::Point2f center = cv::Point2f((width / 2),(height / 2));//図形の中心
    double degree = 45.0;  // 回転角度
    double scale = 0.5; //大きさの定義

ここでは、回転の中心を画像の真ん中に設定し、回転の角度、大きさを指定します。ここで、はじめに画像の横幅、高さを取得しています。また、Point2fは以下のように、(x座標,y座標)のように指定します。

 cv::Point2f center = cv::Point2f(x座標,y座標);//図形の中心

getRotationMatrix2DやwarpAffineはついては以下のように指定します。

タイトル:kaiten_syukusyou2.cpp

cv::getRotationMatrix2D(中心, 回転角度, 大きさ)

タイトル:kaiten_syukusyou3.cpp

cv::warpAffine(元画像, 変換後画像, 変換行列, 画像の大きさ, 補完方法, ピクセル外挿方法,); //画像の変換(アフィン変換)

実装

先ほどのソースコードを用いて、以下のコマンドでコンパイルを行い、実行します。


$ g++ -std=c++11 -o kaiten_syukusyou kaiten_syukusyou.cpp `pkg-config --cflags --libs opencv4 `


$ ./kaiten_syukusyou

その結果が以下の画像です。画像の大きさが半分になり、45度回転していることが確認できました。

画像の拡大縮小warpAffine

また、画像の回転をせず、大きさを2倍にソースコードを変更した場合の結果が以下の画像になります。

    double degree = 0;  // 回転角度
    double scale = 2.0; //大きさの定義

画像2倍

まとめ

本記事では、画像を回転・拡大・縮小するプログラムをC++とOpenCVで作成しました。では要点をまとめます。

cv::rotateで90度回転が可能

getRotationMatrix2DとwarpAffineで、1度ずつ回転が可能で、拡大・縮小もできる

ぜひ、このプログラム通じて、画像処理してみてください!!