スリー3の適当な記事たち

趣味のゲームやアニメ、及びプログラム関係を中心に気楽に書いていきます。

OpenCVで画像を拡大して一部を切り出した画像を出力する

OpenCVを使って画像を拡大して一部を切り出した画像を出力する関数を作ってみました。
要するにズームですね。
言語はC++です。
手法の良し悪しよりも変数名とかコメントとかのだめっぷりが気になってしまいますが、そこは勉強中ということでご勘弁を(笑)

//src画像をcenterを中心に拡大率rateだけズームしてdstに出力する
void zoomPicture(cv::Mat src, cv::Mat dst, cv::Point2i center, double rate)
{
	if (rate < 1.0){//縮小は未対応なのでそのまま
		src.copyTo(dst);
		return;
	}

	cv::Mat resizeSrc;
	cv::resize(src, resizeSrc, cv::Size2i(0, 0), rate, rate);
	//拡大後の拡大中心
	cv::Point2i resizeCenter(center.x*rate, center.y*rate);
		
	//拡大中心と拡大率の設定次第で元の画像をはみ出してしまうので余白を入れる
	int blankHeight = src.rows / 2;//元画像の上下にそれぞれ入れる余白の画素数
	int blankWidth = src.cols / 2;//元画像の左右にそれぞれ入れる余白の画素数
	cv::Mat resizeSrcOnBlank = cv::Mat::zeros(resizeSrc.rows + 2 * blankHeight,resizeSrc.cols + 2 * blankWidth, CV_8UC3);
	resizeSrc.copyTo(resizeSrcOnBlank(cv::Rect(blankWidth, blankHeight, resizeSrc.cols, resizeSrc.rows)));
	resizeSrcOnBlank(cv::Rect(resizeCenter.x+blankWidth - src.cols / 2, resizeCenter.y+blankHeight - src.rows / 2, src.cols, src.rows)).copyTo(dst);
	return;

}

縮小は未対応と書いてありますが、もしかしたら動くかも。
ちなみに入力画像と出力画像は同じサイズを想定しています。

追記6/22
ROIの説明を忘れていました。
Momma's Wiki: OpenCV/ROIの使い方 - Region Of Interest:着目領域(要するにウィンドウ)を使う...
こちらのサイトを参考に、画像の一部をROIとして抽出して、その範囲にコピーすることで背景に画像を重畳するということを実現しています。

追記2016/1/9
ずっと書こうと思って放置していましたがちょっとだけ追記。
この方法だと拡大した画像を一回作ってしまうので拡大率によってはかなり重くなります。
なので軽くしたければ拡大してから切り出すのではなく切り出してから拡大するほうがいいです。
具体的には拡大率と拡大中心から切り出す範囲を計算しROIを指定してそれを元画像のサイズまで拡大することで実現できます。

あと余白処理は拡大中心をずらさないための例外処理なので別の例外処理でもいいです。(僕は今は切り出す範囲が画像をはみ出したらその分切り出す範囲をずらすという例外処理を採用しています。)