OpenCV2.4.9を使い、ズレがある2枚の画像の位置合わせをしようと考えております
アフィン変換で2枚の画像から特徴的な3点を取得し、アフィン変換をつかって片方の画像を補正しようと考えておりますが、
どのような手法で3点を抽出すればよいか悩んでおります。
どなたかC++ ,OpenCV2.4.9環境で実行できるアイディアがあればいただきたいです。
画像位置合わせ opencv アフィン変換
Re: 画像位置合わせ opencv アフィン変換
アフィン変換で平行にして重ねるといいでしょう。
「アフィン変換]の例
「アフィン変換]の例
/**------------------------------------------------------------*
* @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;
}
Re: 画像位置合わせ opencv アフィン変換
ありがとうございます!
アフィン変換のほうはできたのですが、画像から特徴的な3点を自動的に検出できるアイディアがあればお願いします
アフィン変換のほうはできたのですが、画像から特徴的な3点を自動的に検出できるアイディアがあればお願いします
Re: 画像位置合わせ opencv アフィン変換
>画像から特徴的な3点を自動的に検出
どの程度のものが必要なのかについては
問題(≒あなたの用いる画像の状況)に依存するかと思いますので,
「画像 特徴記述子」 とかで検索してみて判断すると良いかと.
#ある程度簡単なものなら「コーナー検出 → 自前で適当なマッチング」とかで済むかもしれませんし.
どの程度のものが必要なのかについては
問題(≒あなたの用いる画像の状況)に依存するかと思いますので,
「画像 特徴記述子」 とかで検索してみて判断すると良いかと.
#ある程度簡単なものなら「コーナー検出 → 自前で適当なマッチング」とかで済むかもしれませんし.