画像位置合わせ opencv アフィン変換

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sql

画像位置合わせ opencv アフィン変換

#1

投稿記事 by sql » 8年前

OpenCV2.4.9を使い、ズレがある2枚の画像の位置合わせをしようと考えております
アフィン変換で2枚の画像から特徴的な3点を取得し、アフィン変換をつかって片方の画像を補正しようと考えておりますが、
どのような手法で3点を抽出すればよいか悩んでおります。
どなたかC++ ,OpenCV2.4.9環境で実行できるアイディアがあればいただきたいです。

と成りのトトロ

Re: 画像位置合わせ opencv アフィン変換

#2

投稿記事 by と成りのトトロ » 8年前

アフィン変換で平行にして重ねるといいでしょう。
「アフィン変換]の例

コード:

/**------------------------------------------------------------*
* @file    overwriteImage.cpp
* @brief   warpAffineを用いて画像内に別の画像を描画する
*          (ピクチャー・イン・ピクチャー機能)
*------------------------------------------------------------*/
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <stdlib.h>
#include <stdio.h>

using namespace std;

const char winName[] = "picture in picture";

/**------------------------------------------------------------*
* @fn          OpenCVのピクチャーインピクチャ
* @brief       画像内に画像を貼り付ける(並行移動量指定)
* @param[in ]  bgImg  背景画像
* @param[in ]  aImg    前景画像
* @param[in ]  tx  前景画像の左上x座標
* @param[in ]  ty  前景画像の左上y座標
*------------------------------------------------------------*/
void PinP_tr(const cv::Mat &bgImg, const cv::Mat &aImg, const int tx, const int ty)
{
	//背景画像の作成
	cv::Mat dstImg = bgImg.clone();

	//前景画像の変形行列
	cv::Mat mat = (cv::Mat_<double>(2, 3) << 1.0, 0.0, tx, 0.0, 1.0, ty);

	//アフィン変換の実行
	cv::warpAffine(aImg, dstImg, mat, dstImg.size(), CV_INTER_LINEAR, cv::BORDER_TRANSPARENT);
	imshow(winName, dstImg);
}

/**------------------------------------------------------------*
* @fn          OpenCVのピクチャーインピクチャ
* @brief       画像内に画像を貼り付ける(回転角度指定)
* @param[in ]  bgImg  背景画像
* @param[in ]  aImg    前景画像
* @param[in ]  angle   回転角度[degree]
*------------------------------------------------------------*/
void PinP_rot(const cv::Mat &bgImg, const cv::Mat &aImg, const double angle)
{
	//背景画像の作成
	cv::Mat dstImg = bgImg.clone();

	//前景画像の変形行列
	cv::Point2d ctr(aImg.cols / 2, aImg.rows / 2);//前景画像の回転中心
	cv::Mat mat = cv::getRotationMatrix2D(ctr, angle, 1.0);//回転行列の作成

	cv::warpAffine(aImg, dstImg, mat, dstImg.size(), CV_INTER_LINEAR, cv::BORDER_TRANSPARENT);
	imshow(winName, dstImg);
}

/**------------------------------------------------------------*
* @fn          OpenCVのピクチャーインピクチャ
* @brief       画像内に画像を貼り付ける(回転角度、移動量指定)
* @param[in ]  bgImg  背景画像
* @param[in ]  aImg    前景画像
* @param[in ]  angle   回転角度[degree]
* @param[in ]  tx  前景画像の左上x座標
* @param[in ]  ty  前景画像の左上y座標
*------------------------------------------------------------*/
void PinP_rot_tr(const cv::Mat &bgImg, const cv::Mat &aImg, const double angle, const double tx, const double ty)
{
	//背景画像の作成
	cv::Mat dstImg = bgImg.clone();

	//前景画像の変形行列
	cv::Point2d ctr(aImg.cols / 2, aImg.rows / 2);//前景画像の回転中心
	cv::Mat mat = cv::getRotationMatrix2D(ctr, angle, 1.0);//回転行列の作成
	mat.at<double>(0, 2) += tx;//回転後の平行移動量
	mat.at<double>(1, 2) += ty;//回転後の平行移動量

							   //アフィン変換の実行
	cv::warpAffine(aImg, dstImg, mat, dstImg.size(), CV_INTER_LINEAR, cv::BORDER_TRANSPARENT);
	imshow(winName, dstImg);
}

/**------------------------------------------------------------*
* @fn          OpenCVのピクチャーインピクチャ
* @brief       画像内に画像を貼り付ける(位置を座標で指定)
* @param[in ]  bgImg  背景画像
* @param[in ]  aImg    前景画像
* @param[in ]  p0  前景画像の左上座標
* @param[in ]  p1  前景画像の右下座標
*------------------------------------------------------------*/
void PinP_point(const cv::Mat &bgImg, const cv::Mat &aImg, const cv::Point2f p0, const cv::Point2f p1)
{
	//背景画像の作成
	cv::Mat dstImg = bgImg.clone();

	//3組の対応点を作成
	vector<cv::Point2f> src, dst;
	src.push_back(cv::Point2f(0, 0));
	src.push_back(cv::Point2f(aImg.cols, 0));
	src.push_back(cv::Point2f(aImg.cols, aImg.rows));

	dst.push_back(p0);
	dst.push_back(cv::Point2f(p1.x, p0.y));
	dst.push_back(p1);

	//前景画像の変形行列
	cv::Mat mat = cv::getAffineTransform(src, dst);

	//アフィン変換の実行
	cv::warpAffine(aImg, dstImg, mat, dstImg.size(), CV_INTER_LINEAR, cv::BORDER_TRANSPARENT);
	imshow(winName, dstImg);
}

/**------------------------------------------------------------*
* @fn          main
* @brief       メイン関数
*------------------------------------------------------------*/
int main(int argc, char** argv)
{
	////////////////////////////// 111
	cv::Mat bgImg, aImg;
	////////////////////////////// 222
	//画像読み込み
	bgImg = cv::imread("b.png");
	aImg = cv::imread("a.png");
	////////////////////////////////////////////////////////////////////// 333
	if ((bgImg.data == NULL) || (aImg.data == NULL))
	{
		printf("------------------------------\n");
		printf("image not exist\n");
		printf("------------------------------\n");
		return EXIT_FAILURE;
	}
	else
	{
		printf("------------------------------\n");
		printf("Press ANY key to progress\n");
		printf("------------------------------\n");
	}
    ////////////////////////////////////////////////////////////////////// 444
	cv::namedWindow(winName); //ウィンドウ生成
	////////////////////////////////////////////////////////////////////// 555 tr
							  //平行移動
	PinP_tr(bgImg, aImg, 100, 100);
	cv::waitKey(0); //キーボード処理
    ////////////////////////////////////////////////////////////////////// 666 rot
					//回転
	PinP_rot(bgImg, aImg, 45);
	cv::waitKey(0); //キーボード処理
    ////////////////////////////////////////////////////////////////////// 777 rot_tr
					//回転+平行移動
	PinP_rot_tr(bgImg, aImg, 45, 100, 100);
	cv::waitKey(0); //キーボード処理
	PinP_point(bgImg, aImg, p0, p1);
    ////////////////////////////////////////////////////////////////////// 888 point
					//座標指定
	cv::Point2f p0(100, 100);
	cv::Point2f p1(450, 380);
	cv::waitKey(0); //キーボード処理
    ///////////////////////////////////////////////////////////////////// 999
	return EXIT_SUCCESS;
}

sql

Re: 画像位置合わせ opencv アフィン変換

#3

投稿記事 by sql » 8年前

ありがとうございます!
アフィン変換のほうはできたのですが、画像から特徴的な3点を自動的に検出できるアイディアがあればお願いします

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 画像位置合わせ opencv アフィン変換

#4

投稿記事 by usao » 8年前

>画像から特徴的な3点を自動的に検出

どの程度のものが必要なのかについては
問題(≒あなたの用いる画像の状況)に依存するかと思いますので,
「画像 特徴記述子」 とかで検索してみて判断すると良いかと.

#ある程度簡単なものなら「コーナー検出 → 自前で適当なマッチング」とかで済むかもしれませんし.

sql

Re: 画像位置合わせ opencv アフィン変換

#5

投稿記事 by sql » 8年前

お二方ご回答ありがとうございました
いただいたアフィン変換のプログラムをもとに、画像特徴子で自力でプログラムしてみます

閉鎖

“C言語何でも質問掲示板” へ戻る