Path: blob/master/modules/calib3d/test/test_homography.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2009, Willow Garage Inc., all rights reserved.14// Copyright (C) 2015, Itseez Inc., all rights reserved.15// Third party copyrights are property of their respective owners.16//17// Redistribution and use in source and binary forms, with or without modification,18// are permitted provided that the following conditions are met:19//20// * Redistribution's of source code must retain the above copyright notice,21// this list of conditions and the following disclaimer.22//23// * Redistribution's in binary form must reproduce the above copyright notice,24// this list of conditions and the following disclaimer in the documentation25// and/or other materials provided with the distribution.26//27// * The name of the copyright holders may not be used to endorse or promote products28// derived from this software without specific prior written permission.29//30// This software is provided by the copyright holders and contributors "as is" and31// any express or implied warranties, including, but not limited to, the implied32// warranties of merchantability and fitness for a particular purpose are disclaimed.33// In no event shall the Intel Corporation or contributors be liable for any direct,34// indirect, incidental, special, exemplary, or consequential damages35// (including, but not limited to, procurement of substitute goods or services;36// loss of use, data, or profits; or business interruption) however caused37// and on any theory of liability, whether in contract, strict liability,38// or tort (including negligence or otherwise) arising in any way out of39// the use of this software, even if advised of the possibility of such damage.40//41//M*/4243#include "test_precomp.hpp"4445namespace opencv_test { namespace {4647#define CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE 148#define CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF 249#define CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF 350#define CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK 451#define CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF 55253#define MESSAGE_MATRIX_SIZE "Homography matrix must have 3*3 sizes."54#define MESSAGE_MATRIX_DIFF "Accuracy of homography transformation matrix less than required."55#define MESSAGE_REPROJ_DIFF_1 "Reprojection error for current pair of points more than required."56#define MESSAGE_REPROJ_DIFF_2 "Reprojection error is not optimal."57#define MESSAGE_RANSAC_MASK_1 "Sizes of inliers/outliers mask are incorrect."58#define MESSAGE_RANSAC_MASK_2 "Mask mustn't have any outliers."59#define MESSAGE_RANSAC_MASK_3 "All values of mask must be 1 (true) or 0 (false)."60#define MESSAGE_RANSAC_MASK_4 "Mask of inliers/outliers is incorrect."61#define MESSAGE_RANSAC_MASK_5 "Inlier in original mask shouldn't be outlier in found mask."62#define MESSAGE_RANSAC_DIFF "Reprojection error for current pair of points more than required."6364#define MAX_COUNT_OF_POINTS 30365#define COUNT_NORM_TYPES 366#define METHODS_COUNT 46768int NORM_TYPE[COUNT_NORM_TYPES] = {cv::NORM_L1, cv::NORM_L2, cv::NORM_INF};69int METHOD[METHODS_COUNT] = {0, cv::RANSAC, cv::LMEDS, cv::RHO};7071using namespace cv;72using namespace std;7374class CV_HomographyTest: public cvtest::ArrayTest75{76public:77CV_HomographyTest();78~CV_HomographyTest();7980void run (int);8182protected:8384int method;85int image_size;86double reproj_threshold;87double sigma;8889private:90float max_diff, max_2diff;91bool check_matrix_size(const cv::Mat& H);92bool check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff);93int check_ransac_mask_1(const Mat& src, const Mat& mask);94int check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask);9596void print_information_1(int j, int N, int method, const Mat& H);97void print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff);98void print_information_3(int method, int j, int N, const Mat& mask);99void print_information_4(int method, int j, int N, int k, int l, double diff);100void print_information_5(int method, int j, int N, int l, double diff);101void print_information_6(int method, int j, int N, int k, double diff, bool value);102void print_information_7(int method, int j, int N, int k, double diff, bool original_value, bool found_value);103void print_information_8(int method, int j, int N, int k, int l, double diff);104};105106CV_HomographyTest::CV_HomographyTest() : max_diff(1e-2f), max_2diff(2e-2f)107{108method = 0;109image_size = 100;110reproj_threshold = 3.0;111sigma = 0.01;112}113114CV_HomographyTest::~CV_HomographyTest() {}115116bool CV_HomographyTest::check_matrix_size(const cv::Mat& H)117{118return (H.rows == 3) && (H.cols == 3);119}120121bool CV_HomographyTest::check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff)122{123diff = cvtest::norm(original, found, norm_type);124return diff <= max_diff;125}126127int CV_HomographyTest::check_ransac_mask_1(const Mat& src, const Mat& mask)128{129if (!(mask.cols == 1) && (mask.rows == src.cols)) return 1;130if (countNonZero(mask) < mask.rows) return 2;131for (int i = 0; i < mask.rows; ++i) if (mask.at<uchar>(i, 0) > 1) return 3;132return 0;133}134135int CV_HomographyTest::check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask)136{137if (!(found_mask.cols == 1) && (found_mask.rows == original_mask.rows)) return 1;138for (int i = 0; i < found_mask.rows; ++i) if (found_mask.at<uchar>(i, 0) > 1) return 2;139return 0;140}141142void CV_HomographyTest::print_information_1(int j, int N, int _method, const Mat& H)143{144cout << endl; cout << "Checking for homography matrix sizes..." << endl; cout << endl;145cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";146cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;147cout << "Count of points: " << N << endl; cout << endl;148cout << "Method: "; if (_method == 0) cout << 0; else if (_method == 8) cout << "RANSAC"; else if (_method == cv::RHO) cout << "RHO"; else cout << "LMEDS"; cout << endl;149cout << "Homography matrix:" << endl; cout << endl;150cout << H << endl; cout << endl;151cout << "Number of rows: " << H.rows << " Number of cols: " << H.cols << endl; cout << endl;152}153154void CV_HomographyTest::print_information_2(int j, int N, int _method, const Mat& H, const Mat& H_res, int k, double diff)155{156cout << endl; cout << "Checking for accuracy of homography matrix computing..." << endl; cout << endl;157cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";158cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;159cout << "Count of points: " << N << endl; cout << endl;160cout << "Method: "; if (_method == 0) cout << 0; else if (_method == 8) cout << "RANSAC"; else if (_method == cv::RHO) cout << "RHO"; else cout << "LMEDS"; cout << endl;161cout << "Original matrix:" << endl; cout << endl;162cout << H << endl; cout << endl;163cout << "Found matrix:" << endl; cout << endl;164cout << H_res << endl; cout << endl;165cout << "Norm type using in criteria: "; if (NORM_TYPE[k] == 1) cout << "INF"; else if (NORM_TYPE[k] == 2) cout << "L1"; else cout << "L2"; cout << endl;166cout << "Difference between matrices: " << diff << endl;167cout << "Maximum allowed difference: " << max_diff << endl; cout << endl;168}169170void CV_HomographyTest::print_information_3(int _method, int j, int N, const Mat& mask)171{172cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;173cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";174cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;175cout << "Count of points: " << N << endl; cout << endl;176cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;177cout << "Found mask:" << endl; cout << endl;178cout << mask << endl; cout << endl;179cout << "Number of rows: " << mask.rows << " Number of cols: " << mask.cols << endl; cout << endl;180}181182void CV_HomographyTest::print_information_4(int _method, int j, int N, int k, int l, double diff)183{184cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;185cout << "Method: "; if (_method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;186cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";187cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;188cout << "Sigma of normal noise: " << sigma << endl;189cout << "Count of points: " << N << endl;190cout << "Number of point: " << k << endl;191cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;192cout << "Difference with noise of point: " << diff << endl;193cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;194}195196void CV_HomographyTest::print_information_5(int _method, int j, int N, int l, double diff)197{198cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;199cout << "Method: "; if (_method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;200cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";201cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;202cout << "Sigma of normal noise: " << sigma << endl;203cout << "Count of points: " << N << endl;204cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;205cout << "Difference with noise of points: " << diff << endl;206cout << "Maxumum allowed difference: " << max_diff << endl; cout << endl;207}208209void CV_HomographyTest::print_information_6(int _method, int j, int N, int k, double diff, bool value)210{211cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;212cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;213cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";214cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;215cout << "Count of points: " << N << " " << endl;216cout << "Number of point: " << k << " " << endl;217cout << "Reprojection error for this point: " << diff << " " << endl;218cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;219cout << "Value of found mask: "<< value << endl; cout << endl;220}221222void CV_HomographyTest::print_information_7(int _method, int j, int N, int k, double diff, bool original_value, bool found_value)223{224cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;225cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;226cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";227cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;228cout << "Count of points: " << N << " " << endl;229cout << "Number of point: " << k << " " << endl;230cout << "Reprojection error for this point: " << diff << " " << endl;231cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;232cout << "Value of original mask: "<< original_value << " Value of found mask: " << found_value << endl; cout << endl;233}234235void CV_HomographyTest::print_information_8(int _method, int j, int N, int k, int l, double diff)236{237cout << endl; cout << "Checking for reprojection error of inlier..." << endl; cout << endl;238cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;239cout << "Sigma of normal noise: " << sigma << endl;240cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";241cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;242cout << "Count of points: " << N << " " << endl;243cout << "Number of point: " << k << " " << endl;244cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;245cout << "Difference with noise of point: " << diff << endl;246cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;247}248249void CV_HomographyTest::run(int)250{251for (int N = 4; N <= MAX_COUNT_OF_POINTS; ++N)252{253RNG& rng = ts->get_rng();254255float *src_data = new float [2*N];256257for (int i = 0; i < N; ++i)258{259src_data[2*i] = (float)cvtest::randReal(rng)*image_size;260src_data[2*i+1] = (float)cvtest::randReal(rng)*image_size;261}262263cv::Mat src_mat_2f(1, N, CV_32FC2, src_data),264src_mat_2d(2, N, CV_32F, src_data),265src_mat_3d(3, N, CV_32F);266cv::Mat dst_mat_2f, dst_mat_2d, dst_mat_3d;267268vector <Point2f> src_vec, dst_vec;269270for (int i = 0; i < N; ++i)271{272float *tmp = src_mat_2d.ptr<float>()+2*i;273src_mat_3d.at<float>(0, i) = tmp[0];274src_mat_3d.at<float>(1, i) = tmp[1];275src_mat_3d.at<float>(2, i) = 1.0f;276277src_vec.push_back(Point2f(tmp[0], tmp[1]));278}279280double fi = cvtest::randReal(rng)*2*CV_PI;281282double t_x = cvtest::randReal(rng)*sqrt(image_size*1.0),283t_y = cvtest::randReal(rng)*sqrt(image_size*1.0);284285double Hdata[9] = { cos(fi), -sin(fi), t_x,286sin(fi), cos(fi), t_y,2870.0f, 0.0f, 1.0f };288289cv::Mat H_64(3, 3, CV_64F, Hdata), H_32;290291H_64.convertTo(H_32, CV_32F);292293dst_mat_3d = H_32*src_mat_3d;294295dst_mat_2d.create(2, N, CV_32F); dst_mat_2f.create(1, N, CV_32FC2);296297for (int i = 0; i < N; ++i)298{299float *tmp_2f = dst_mat_2f.ptr<float>()+2*i;300tmp_2f[0] = dst_mat_2d.at<float>(0, i) = dst_mat_3d.at<float>(0, i) /= dst_mat_3d.at<float>(2, i);301tmp_2f[1] = dst_mat_2d.at<float>(1, i) = dst_mat_3d.at<float>(1, i) /= dst_mat_3d.at<float>(2, i);302dst_mat_3d.at<float>(2, i) = 1.0f;303304dst_vec.push_back(Point2f(tmp_2f[0], tmp_2f[1]));305}306307for (int i = 0; i < METHODS_COUNT; ++i)308{309method = METHOD[i];310switch (method)311{312case 0:313case LMEDS:314{315Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method),316cv::findHomography(src_mat_2f, dst_vec, method),317cv::findHomography(src_vec, dst_mat_2f, method),318cv::findHomography(src_vec, dst_vec, method) };319320for (int j = 0; j < 4; ++j)321{322323if (!check_matrix_size(H_res_64[j]))324{325print_information_1(j, N, method, H_res_64[j]);326CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);327return;328}329330double diff;331332for (int k = 0; k < COUNT_NORM_TYPES; ++k)333if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))334{335print_information_2(j, N, method, H_64, H_res_64[j], k, diff);336CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);337return;338}339}340341continue;342}343case cv::RHO:344case RANSAC:345{346cv::Mat mask [4]; double diff;347348Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method, reproj_threshold, mask[0]),349cv::findHomography(src_mat_2f, dst_vec, method, reproj_threshold, mask[1]),350cv::findHomography(src_vec, dst_mat_2f, method, reproj_threshold, mask[2]),351cv::findHomography(src_vec, dst_vec, method, reproj_threshold, mask[3]) };352353for (int j = 0; j < 4; ++j)354{355356if (!check_matrix_size(H_res_64[j]))357{358print_information_1(j, N, method, H_res_64[j]);359CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);360return;361}362363for (int k = 0; k < COUNT_NORM_TYPES; ++k)364if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))365{366print_information_2(j, N, method, H_64, H_res_64[j], k, diff);367CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);368return;369}370371int code = check_ransac_mask_1(src_mat_2f, mask[j]);372373if (code)374{375print_information_3(method, j, N, mask[j]);376377switch (code)378{379case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }380case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_2); break; }381case 3: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }382383default: break;384}385386return;387}388389}390391continue;392}393394default: continue;395}396}397398Mat noise_2f(1, N, CV_32FC2);399rng.fill(noise_2f, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma));400401cv::Mat mask(N, 1, CV_8UC1);402403for (int i = 0; i < N; ++i)404{405float *a = noise_2f.ptr<float>()+2*i, *_2f = dst_mat_2f.ptr<float>()+2*i;406_2f[0] += a[0]; _2f[1] += a[1];407mask.at<bool>(i, 0) = !(sqrt(a[0]*a[0]+a[1]*a[1]) > reproj_threshold);408}409410for (int i = 0; i < METHODS_COUNT; ++i)411{412method = METHOD[i];413switch (method)414{415case 0:416case LMEDS:417{418Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f),419cv::findHomography(src_mat_2f, dst_vec),420cv::findHomography(src_vec, dst_mat_2f),421cv::findHomography(src_vec, dst_vec) };422423for (int j = 0; j < 4; ++j)424{425426if (!check_matrix_size(H_res_64[j]))427{428print_information_1(j, N, method, H_res_64[j]);429CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);430return;431}432433Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);434435cv::Mat dst_res_3d(3, N, CV_32F), noise_2d(2, N, CV_32F);436437for (int k = 0; k < N; ++k)438{439440Mat tmp_mat_3d = H_res_32*src_mat_3d.col(k);441442dst_res_3d.at<float>(0, k) = tmp_mat_3d.at<float>(0, 0) /= tmp_mat_3d.at<float>(2, 0);443dst_res_3d.at<float>(1, k) = tmp_mat_3d.at<float>(1, 0) /= tmp_mat_3d.at<float>(2, 0);444dst_res_3d.at<float>(2, k) = tmp_mat_3d.at<float>(2, 0) = 1.0f;445446float *a = noise_2f.ptr<float>()+2*k;447noise_2d.at<float>(0, k) = a[0]; noise_2d.at<float>(1, k) = a[1];448449for (int l = 0; l < COUNT_NORM_TYPES; ++l)450if (cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]) > max_2diff)451{452print_information_4(method, j, N, k, l, cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]));453CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_1);454return;455}456457}458459for (int l = 0; l < COUNT_NORM_TYPES; ++l)460if (cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]) > max_diff)461{462print_information_5(method, j, N, l, cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]));463CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_2);464return;465}466467}468469continue;470}471case cv::RHO:472case RANSAC:473{474cv::Mat mask_res [4];475476Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method, reproj_threshold, mask_res[0]),477cv::findHomography(src_mat_2f, dst_vec, method, reproj_threshold, mask_res[1]),478cv::findHomography(src_vec, dst_mat_2f, method, reproj_threshold, mask_res[2]),479cv::findHomography(src_vec, dst_vec, method, reproj_threshold, mask_res[3]) };480481for (int j = 0; j < 4; ++j)482{483if (!check_matrix_size(H_res_64[j]))484{485print_information_1(j, N, method, H_res_64[j]);486CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);487return;488}489490int code = check_ransac_mask_2(mask, mask_res[j]);491492if (code)493{494print_information_3(method, j, N, mask_res[j]);495496switch (code)497{498case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }499case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }500501default: break;502}503504return;505}506507cv::Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);508509cv::Mat dst_res_3d = H_res_32*src_mat_3d;510511for (int k = 0; k < N; ++k)512{513dst_res_3d.at<float>(0, k) /= dst_res_3d.at<float>(2, k);514dst_res_3d.at<float>(1, k) /= dst_res_3d.at<float>(2, k);515dst_res_3d.at<float>(2, k) = 1.0f;516517float *p = dst_mat_2f.ptr<float>()+2*k;518519dst_mat_3d.at<float>(0, k) = p[0];520dst_mat_3d.at<float>(1, k) = p[1];521522double diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_L2);523524if (mask_res[j].at<bool>(k, 0) != (diff <= reproj_threshold))525{526print_information_6(method, j, N, k, diff, mask_res[j].at<bool>(k, 0));527CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_4);528return;529}530531if (mask.at<bool>(k, 0) && !mask_res[j].at<bool>(k, 0))532{533print_information_7(method, j, N, k, diff, mask.at<bool>(k, 0), mask_res[j].at<bool>(k, 0));534CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_5);535return;536}537538if (mask_res[j].at<bool>(k, 0))539{540float *a = noise_2f.ptr<float>()+2*k;541dst_mat_3d.at<float>(0, k) -= a[0];542dst_mat_3d.at<float>(1, k) -= a[1];543544cv::Mat noise_2d(2, 1, CV_32F);545noise_2d.at<float>(0, 0) = a[0]; noise_2d.at<float>(1, 0) = a[1];546547for (int l = 0; l < COUNT_NORM_TYPES; ++l)548{549diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_TYPE[l]);550551if (diff - cv::norm(noise_2d, NORM_TYPE[l]) > max_2diff)552{553print_information_8(method, j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l]));554CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF, MESSAGE_RANSAC_DIFF);555return;556}557}558}559}560}561562continue;563}564565default: continue;566}567}568569delete[]src_data;570src_data = NULL;571}572}573574TEST(Calib3d_Homography, accuracy) { CV_HomographyTest test; test.safe_run(); }575576TEST(Calib3d_Homography, EKcase)577{578float pt1data[] =579{5802.80073029e+002f, 2.39591217e+002f, 2.21912201e+002f, 2.59783997e+002f,5812.16053192e+002f, 2.78826569e+002f, 2.22782532e+002f, 2.82330383e+002f,5822.09924820e+002f, 2.89122559e+002f, 2.11077698e+002f, 2.89384674e+002f,5832.25287689e+002f, 2.88795532e+002f, 2.11180801e+002f, 2.89653503e+002f,5842.24126404e+002f, 2.90466064e+002f, 2.10914429e+002f, 2.90886963e+002f,5852.23439362e+002f, 2.91657715e+002f, 2.24809387e+002f, 2.91891602e+002f,5862.09809082e+002f, 2.92891113e+002f, 2.08771164e+002f, 2.93093231e+002f,5872.23160095e+002f, 2.93259460e+002f, 2.07874023e+002f, 2.93989990e+002f,5882.08963638e+002f, 2.94209839e+002f, 2.23963165e+002f, 2.94479645e+002f,5892.23241791e+002f, 2.94887817e+002f, 2.09438782e+002f, 2.95233337e+002f,5902.08901886e+002f, 2.95762878e+002f, 2.21867981e+002f, 2.95747711e+002f,5912.24195511e+002f, 2.98270905e+002f, 2.09331345e+002f, 3.05958191e+002f,5922.24727875e+002f, 3.07186035e+002f, 2.26718842e+002f, 3.08095795e+002f,5932.25363953e+002f, 3.08200226e+002f, 2.19897797e+002f, 3.13845093e+002f,5942.25013474e+002f, 3.15558777e+002f595};596597float pt2data[] =598{5991.84072723e+002f, 1.43591202e+002f, 1.25912483e+002f, 1.63783859e+002f,6002.06439407e+002f, 2.20573929e+002f, 1.43801437e+002f, 1.80703903e+002f,6019.77904129e+000f, 2.49660202e+002f, 1.38458405e+001f, 2.14502701e+002f,6021.50636337e+002f, 2.15597183e+002f, 6.43103180e+001f, 2.51667648e+002f,6031.54952499e+002f, 2.20780014e+002f, 1.26638412e+002f, 2.43040924e+002f,6043.67568909e+002f, 1.83624954e+001f, 1.60657944e+002f, 2.21794052e+002f,605-1.29507828e+000f, 3.32472443e+002f, 8.51442242e+000f, 4.15561554e+002f,6061.27161377e+002f, 1.97260361e+002f, 5.40714645e+000f, 4.90978302e+002f,6072.25571690e+001f, 3.96912415e+002f, 2.95664978e+002f, 7.36064959e+000f,6081.27241104e+002f, 1.98887573e+002f, -1.25569367e+000f, 3.87713226e+002f,6091.04194012e+001f, 4.31495758e+002f, 1.25868874e+002f, 1.99751617e+002f,6101.28195480e+002f, 2.02270355e+002f, 2.23436356e+002f, 1.80489182e+002f,6111.28727692e+002f, 2.11185410e+002f, 2.03336639e+002f, 2.52182083e+002f,6121.29366486e+002f, 2.12201904e+002f, 1.23897598e+002f, 2.17847351e+002f,6131.29015259e+002f, 2.19560623e+002f614};615616int npoints = (int)(sizeof(pt1data)/sizeof(pt1data[0])/2);617618Mat p1(1, npoints, CV_32FC2, pt1data);619Mat p2(1, npoints, CV_32FC2, pt2data);620Mat mask;621622Mat h = findHomography(p1, p2, RANSAC, 0.01, mask);623ASSERT_TRUE(!h.empty());624625cv::transpose(mask, mask);626Mat p3, mask2;627int ninliers = countNonZero(mask);628Mat nmask[] = { mask, mask };629merge(nmask, 2, mask2);630perspectiveTransform(p1, p3, h);631mask2 = mask2.reshape(1);632p2 = p2.reshape(1);633p3 = p3.reshape(1);634double err = cvtest::norm(p2, p3, NORM_INF, mask2);635636printf("ninliers: %d, inliers err: %.2g\n", ninliers, err);637ASSERT_GE(ninliers, 10);638ASSERT_LE(err, 0.01);639}640641TEST(Calib3d_Homography, fromImages)642{643Mat img_1 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image1.png", 0);644Mat img_2 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image2.png", 0);645Ptr<ORB> orb = ORB::create();646vector<KeyPoint> keypoints_1, keypoints_2;647Mat descriptors_1, descriptors_2;648orb->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1, false );649orb->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2, false );650651//-- Step 3: Matching descriptor vectors using Brute Force matcher652BFMatcher matcher(NORM_HAMMING,false);653std::vector< DMatch > matches;654matcher.match( descriptors_1, descriptors_2, matches );655656double max_dist = 0; double min_dist = 100;657//-- Quick calculation of max and min distances between keypoints658for( int i = 0; i < descriptors_1.rows; i++ )659{660double dist = matches[i].distance;661if( dist < min_dist ) min_dist = dist;662if( dist > max_dist ) max_dist = dist;663}664665//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )666std::vector< DMatch > good_matches;667for( int i = 0; i < descriptors_1.rows; i++ )668{669if( matches[i].distance <= 100 )670good_matches.push_back( matches[i]);671}672673//-- Localize the model674std::vector<Point2f> pointframe1;675std::vector<Point2f> pointframe2;676for( int i = 0; i < (int)good_matches.size(); i++ )677{678//-- Get the keypoints from the good matches679pointframe1.push_back( keypoints_1[ good_matches[i].queryIdx ].pt );680pointframe2.push_back( keypoints_2[ good_matches[i].trainIdx ].pt );681}682683Mat H0, H1, inliers0, inliers1;684double min_t0 = DBL_MAX, min_t1 = DBL_MAX;685for( int i = 0; i < 10; i++ )686{687double t = (double)getTickCount();688H0 = findHomography( pointframe1, pointframe2, RANSAC, 3.0, inliers0 );689t = (double)getTickCount() - t;690min_t0 = std::min(min_t0, t);691}692int ninliers0 = countNonZero(inliers0);693for( int i = 0; i < 10; i++ )694{695double t = (double)getTickCount();696H1 = findHomography( pointframe1, pointframe2, RHO, 3.0, inliers1 );697t = (double)getTickCount() - t;698min_t1 = std::min(min_t1, t);699}700int ninliers1 = countNonZero(inliers1);701double freq = getTickFrequency();702printf("nfeatures1 = %d, nfeatures2=%d, matches=%d, ninliers(RANSAC)=%d, "703"time(RANSAC)=%.2fmsec, ninliers(RHO)=%d, time(RHO)=%.2fmsec\n",704(int)keypoints_1.size(), (int)keypoints_2.size(),705(int)good_matches.size(), ninliers0, min_t0*1000./freq, ninliers1, min_t1*1000./freq);706707ASSERT_TRUE(!H0.empty());708ASSERT_GE(ninliers0, 80);709ASSERT_TRUE(!H1.empty());710ASSERT_GE(ninliers1, 80);711}712713}} // namespace714715716