4点同士の対応点情報からホモグラフィを線型に求める

Mat findHomography(InputArray src, InputArray dst, int method, double ransacReprojThreshold, OutputArray mask, const int maxIters, const double confidence)†

引数†

返り値†

Mat findHomography(InputArray src, InputArray dst, OutputArray mask, int method, double ransacReprojThreshold);†

引数†

返り値†

解説†

methodについて†

導出†

#mimetex(\left(\begin{array}{ccc}h_{11}&h_{12}&h_{13}\\h_{21}&h_{22}&h_{23}\\h_{31}&h_{32}&1\\\end{array}\right)\left(\begin{array}{c}x\\y\\1\\\end{array}\right)=\left(\begin{array}{c}sx^\prime\\sy^\prime\\s\\\end{array}\right))

#mimetex(\left\{\begin{array}{l}h_{11}x+h_{12}y+h_{13}=sx^\prime\\h_{21}x+h_{22}y+h_{23}=sy^\prime\\h_{31}x+h_{32}y+1=s\\\end{array})

#mimetex(\left\{\begin{array}{c}h_{11}x+h_{12}y+h_{13}&=\(h_{31}x+h_{32}y+1\)x^\prime\\h_{21}x+h_{22}y+h_{23}&=\(h_{31}x+h_{32}y+1\)y^\prime\\\end{array})

#mimetex(\left\{\begin{array}{c}h_{11}x+h_{12}y+h_{13}-h_{31}xx^\prime-h_{32}yx^\prime&=x^\prime\\h_{21}x+h_{22}y+h_{23}-h_{31}xy^\prime-h_{32}yy^\prime&=y^\prime\\\end{array})

#mimetex(\left(\begin{array}{cccccccc}x&y&1&0&0&0&-xx^\prime&-yx^\prime\\0&0&0&x&y&1&-xy^\prime&-yy^\prime\\\end{array}\right)\left(\begin{array}{c}h_{11}\\h_{12}\\h_{13}\\h_{21}\\h_{22}\\h_{23}\\h_{31}\\h_{32}\\\end{array}\right)=\left(\begin{array}{c}x^\prime\\y^\prime\\\end{array}\right))

#mimetex(\left(\begin{array}{cccccccc}x_1&y_1&1&0&0&0&-x_1x_1^\prime&-y_1x_1^\prime\\0&0&0&x_1&y_1&1&-x_1y_1^\prime&-y_1y_1^\prime\\x_2&y_2&1&0&0&0&-x_2x_2^\prime&-y_2x_2^\prime\\0&0&0&x_2&y_2&1&-x_2y_2^\prime&-y_2y_2^\prime\\x_3&y_3&1&0&0&0&-x_3x_3^\prime&-y_3x_3^\prime\\0&0&0&x_3&y_3&1&-x_3y_3^\prime&-y_3y_3^\prime\\x_4&y_4&1&0&0&0&-x_4x_4^\prime&-y_4x_4^\prime\\0&0&0&x_4&y_4&1&-x_4y_4^\prime&-y_4y_4^\prime\\\end{array}\right)\left(\begin{array}{c}h_{11}\\h_{12}\\h_{13}\\h_{21}\\h_{22}\\h_{23}\\h_{31}\\h_{32}\\\end{array}\right)=\left(\begin{array}{c}x_1^\prime\\y_1^\prime\\x_2^\prime\\y_2^\prime\\x_3^\prime\\y_3^\prime\\x_4^\prime\\y_4^\prime\\\end{array}\right))

#mimetex(\rm{A}\rm{X}=\rm{B})

サンプルコード†

const char inputForegroundImageFilename[] = "file/path/to/opencv/samples/data/box.png"; const char inputBackgroundImageFilename[] = "file/path/to/opencv/samples/data/box_in_scene.png"; const unsigned char kHigh = 255; const double kSigma = 1.0;

const double srcPoints[] = {

	224, 53,1,145,161,1,240,185,1,204,135,1,159,174,1,200,63, 1,236,154,1,229,163,1,170,170,1,
	218,155,1,237,152,1, 83, 54,1,188,166,1, 95,145,1,201,193,1,132,140,1,180,159,1,150, 46,1,
	180,183,1,180,132,1,155,152,1,145, 93,1, 63,132,1, 89,101,1,148, 95,1,228,130,1,210,147,1,
	133,175,1,154, 44,1, 70, 89,1,167,146,1,158,167,1,166,150,1,159, 85,1, 53, 73,1, 37, 91,1,
	 90,117,1,107,163,1,

};

const double dstPoints[] = {

	243, 53,1,173,249,1,222,269,1,207,239,1,179,257,1,211,199,1,223,250,1,218,256,1,186,256,1,
	213,251,1,223,250,1,152,191,1,195,254,1,147,237,1,338,324,1,168,234,1,192,252,1,188,190,1,
	190,264,1,194,235,1,187,298,1,181,213,1,133,229,1,149,214,1,349,320,1,218,256,1,209,247,1,
	163,255,1,188,190,1,176,239,1,185,245,1,278,156,1,185,245,1,370,288,1,136,198,1,149,214,1,
	149,230,1,123,264,1,

}; const unsigned int cPoints = 38; const cv::Scalar lineColor = cv::Scalar(kHigh,kHigh,kHigh,0);

void drawCorrespondingLine(const cv::Mat& foreground, const cv::Mat& background, cv::Mat& result, const cv::Mat& src, const cv::Mat& dst, const cv::Mat Mask) {

	using namespace cv;
	int heightDiff = background.rows - foreground.rows;
	if(heightDiff < 0)
	{
		// to connect in one image, foreground image must be equall or shorter than background in height
		result = background.clone();
		return;
	}
	Mat object;
	Mat space;
	if(heightDiff > 0)
	{
		// add a blank space below the foreground
		space = Mat(heightDiff, foreground.cols, CV_8UC1);
		vconcat(foreground, space, object);
	}
	else
	{
		// foreground and background are same height
		// just copy the foreground
		object = foreground.clone();
	}
	// concatenate them horizontally
	hconcat(object, background, result);
	// draw lines
	for(int iColumn = 0;iColumn < dst.rows;iColumn++)
	{
		if(Mask.data[iColumn] != 0)
		{
			Point objPoint  = Point((int)src.at<double>(iColumn, 0),                 (int)src.at<double>(iColumn, 1));
			Point backPoint = Point((int)dst.at<double>(iColumn, 0)+foreground.cols, (int)dst.at<double>(iColumn, 1));
			line(result, objPoint, backPoint, lineColor);
		}
	}

}

void estimateHomography(cv::Mat& src, cv::Mat& dst, int method, const char* windowName) {

	using namespace cv;
	Mat pointMask  = src.clone();
	Mat homography = Mat(3, 3, CV_64FC1);
	// estimate the homography
	homography = findHomography(src, dst, method, 3.0f, pointMask);
	Mat foreground = imread(inputForegroundImageFilename, IMREAD_GRAYSCALE);
	Mat background = imread(inputBackgroundImageFilename, IMREAD_GRAYSCALE);
	Mat result     = background.clone();
	Mat whiteImage = Mat().zeros(foreground.size(), CV_8UC1);
	Mat maskImage  = Mat().zeros(background.size(), CV_8UC1);
	Mat correspondence;
	// draw lines between corresponding lines
	drawCorrespondingLine(foreground, background, correspondence, src, dst, pointMask);
	// warp the image based on homography
	warpPerspective(foreground, result, homography, result.size(),INTER_LINEAR, BORDER_TRANSPARENT);
	// resize the mask to show which points are used
	resize(pointMask, pointMask, Size(20, background.rows), 0, 0, INTER_NEAREST);
	pointMask.convertTo(pointMask, CV_8U);
	pointMask *= kHigh;
	// concatenate them horizontally
	std::vector<Mat> inputLists;
	inputLists.push_back(correspondence);
	inputLists.push_back(result.clone());
	inputLists.push_back(pointMask);
	hconcat(inputLists, result);
	// show the image
	namedWindow(windowName);
	imshow(windowName, result);
	waitKey(0);
	destroyAllWindows();

};

int main(int argc, char **argv){

	using namespace cv;
	Mat src        = Mat(cPoints, 3, CV_64FC1, (void*)srcPoints);
	Mat dst        = Mat(cPoints, 3, CV_64FC1, (void*)dstPoints);
	// estimate homography using default method
	estimateHomography(src, dst, 0,      "default");
	// estimate homography using RANSAC estimation method
	estimateHomography(src, dst, RANSAC, "RANSAC");
	// estimate homography using LMeDS estimation method
	estimateHomography(src, dst, LMEDS,  "LMeDS");
	// estimate homography using RHO estimation method
	estimateHomography(src, dst, RHO,    "RHO");
	// estimate homography with some noise on the coordinates
	// in order to show the tolerance against the noise
	Mat srcNoiseAdded = src.clone();
	Mat dstNoiseAdded = dst.clone();
	RNG noise;
	// add gaussian noise
	for(int i = 0;i < src.rows;i++)
	{
		srcNoiseAdded.at<double>(i,0) += noise.gaussian(kSigma);
		srcNoiseAdded.at<double>(i,1) += noise.gaussian(kSigma);
		dstNoiseAdded.at<double>(i,0) += noise.gaussian(kSigma);
		dstNoiseAdded.at<double>(i,1) += noise.gaussian(kSigma);
	}
	// estimate the homography using each method
	estimateHomography(srcNoiseAdded, dstNoiseAdded, RANSAC, "RANSAC");
	estimateHomography(srcNoiseAdded, dstNoiseAdded, LMEDS,  "LMeDS");
	estimateHomography(srcNoiseAdded, dstNoiseAdded, RHO,    "RHO");
	// estimate homography with wrong correspondence
	// add ranndom correspondence coordinates and see if estimation can reject them
	srcNoiseAdded = src.clone();
	dstNoiseAdded = dst.clone();
	// fill the noisePart with random coordinates
	// concatenate them using push_back()
	Mat noisePart = Mat(20, 3, CV_64FC1);
	noise.fill(noisePart, RNG::UNIFORM, Mat::zeros(1, 1, CV_64FC1), Mat::ones(1, 1, CV_64FC1) * 200);
	srcNoiseAdded.push_back(noisePart);
	noise.fill(noisePart, RNG::UNIFORM, Mat::zeros(1, 1, CV_64FC1), Mat::ones(1, 1, CV_64FC1) * 200);
	dstNoiseAdded.push_back(noisePart);
	// estimate the homography using each method
	estimateHomography(srcNoiseAdded, dstNoiseAdded, RANSAC, "RANSAC");
	estimateHomography(srcNoiseAdded, dstNoiseAdded, LMEDS,  "LMeDS");
	estimateHomography(srcNoiseAdded, dstNoiseAdded, RHO,    "RHO");
	return 0;

} }}

実行結果†

実体ファイル†

OpenCV 3.0系列†

OpenCV 2.4系列†

その他†

ジャンル:OpenCV:OpenCV 2.4:OpenCV 3.0:OpenCV 3.1準拠


*1 厳密には等式(=)でなく,相似&mimetex(\(\simeq\

添付ファイル: fileresult000-noEstimation.png 1861件 [詳細] fileresult001-RANSAC.png 1699件 [詳細] fileresult002-LMeD.png 1757件 [詳細] fileresult003-RHO.png 1774件 [詳細] fileresult004.png 1648件 [詳細] fileresult004-RansacWithNoise.png 1784件 [詳細] fileresult005-LmedWithNoise.png 1729件 [詳細] fileresult006-RhoWithNoise.png 1763件 [詳細] fileresult007-RansacWithWrongCorrespondence.png 1654件 [詳細] fileresult008-LmedWithWrongCorrespondence.png 1678件 [詳細] fileresult009-RhoWithWrongCorrespondence.png 1644件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-01-14 (木) 12:32:40