1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge branch '4.x' into '5.x'

This commit is contained in:
Maksim Shabunin
2024-06-11 19:38:59 +03:00
573 changed files with 72922 additions and 7355 deletions
+13 -23
View File
@@ -6,7 +6,7 @@
#define OPENCV_3D_HPP
#include "opencv2/core.hpp"
#include "opencv2/core/types_c.h"
#include "opencv2/core/utils/logger.hpp"
#include "opencv2/3d/depth.hpp"
#include "opencv2/3d/odometry.hpp"
@@ -792,8 +792,8 @@ correctly only when there are more than 50% of inliers. Finally, if there are no
noise is rather small, use the default method (method=0).
The function is used to find initial intrinsic and extrinsic matrices. Homography matrix is
determined up to a scale. Thus, it is normalized so that \f$h_{33}=1\f$. Note that whenever an \f$H\f$ matrix
cannot be estimated, an empty one will be returned.
determined up to a scale. If \f$h_{33}\f$ is non-zero, the matrix is normalized so that \f$h_{33}=1\f$.
@note Whenever an \f$H\f$ matrix cannot be estimated, an empty one will be returned.
@sa
getAffineTransform, estimateAffine2D, estimateAffinePartial2D, getPerspectiveTransform, warpPerspective,
@@ -1407,13 +1407,13 @@ CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2,
@param points1 Array of N (N \>= 5) 2D points from the first image. The point coordinates should
be floating-point (single or double precision).
@param points2 Array of the second image points of the same size and format as points1 .
@param points2 Array of the second image points of the same size and format as points1.
@param cameraMatrix Camera intrinsic matrix \f$\cameramatrix{A}\f$ .
Note that this function assumes that points1 and points2 are feature points from cameras with the
same camera intrinsic matrix. If this assumption does not hold for your use case, use
#undistortPoints with `P = cv::NoArray()` for both cameras to transform image points
to normalized image coordinates, which are valid for the identity camera intrinsic matrix. When
passing these coordinates, pass the identity matrix for this parameter.
same camera intrinsic matrix. If this assumption does not hold for your use case, use another
function overload or #undistortPoints with `P = cv::NoArray()` for both cameras to transform image
points to normalized image coordinates, which are valid for the identity camera intrinsic matrix.
When passing these coordinates, pass the identity matrix for this parameter.
@param method Method for computing an essential matrix.
- @ref RANSAC for the RANSAC algorithm.
- @ref LMEDS for the LMedS algorithm.
@@ -1487,23 +1487,13 @@ Mat findEssentialMat(
@param points1 Array of N (N \>= 5) 2D points from the first image. The point coordinates should
be floating-point (single or double precision).
@param points2 Array of the second image points of the same size and format as points1 .
@param cameraMatrix1 Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
Note that this function assumes that points1 and points2 are feature points from cameras with the
same camera matrix. If this assumption does not hold for your use case, use
#undistortPoints with `P = cv::NoArray()` for both cameras to transform image points
to normalized image coordinates, which are valid for the identity camera matrix. When
passing these coordinates, pass the identity matrix for this parameter.
@param cameraMatrix2 Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
Note that this function assumes that points1 and points2 are feature points from cameras with the
same camera matrix. If this assumption does not hold for your use case, use
#undistortPoints with `P = cv::NoArray()` for both cameras to transform image points
to normalized image coordinates, which are valid for the identity camera matrix. When
passing these coordinates, pass the identity matrix for this parameter.
@param distCoeffs1 Input vector of distortion coefficients
@param points2 Array of the second image points of the same size and format as points1.
@param cameraMatrix1 Camera matrix for the first camera \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
@param cameraMatrix2 Camera matrix for the second camera \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
@param distCoeffs1 Input vector of distortion coefficients for the first camera
\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$
of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed.
@param distCoeffs2 Input vector of distortion coefficients
@param distCoeffs2 Input vector of distortion coefficients for the second camera
\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$
of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed.
@param method Method for computing an essential matrix.
+124 -7
View File
@@ -41,6 +41,7 @@
//M*/
#include "precomp.hpp"
#include "hal_replacement.hpp"
#include "distortion_model.hpp"
#include <stdio.h>
#include <iterator>
@@ -539,20 +540,15 @@ void cv::projectPoints( InputArray _objectPoints,
(objectPoints.rows == count && objpt_cn*objectPoints.cols == 3) ||
(objectPoints.rows == 3 && objpt_cn == 1 && objectPoints.cols == count));
Mat matM(objectPoints.size(), CV_64FC(objpt_cn));
objectPoints.convertTo(matM, CV_64F);
if (objectPoints.rows == 3 && objectPoints.cols == count) {
Mat temp;
transpose(matM, temp);
matM = temp;
transpose(objectPoints, temp);
objectPoints = temp;
}
CV_Assert( _imagePoints.needed() );
_imagePoints.create(count, 1, CV_MAKETYPE(objpt_depth, 2), -1, true);
Mat ipoints = _imagePoints.getMat();
ipoints.convertTo(_m, CV_64F);
const Point3d* M = matM.ptr<Point3d>();
Point2d* m = _m.ptr<Point2d>();
Mat rvec = _rvec.getMat(), tvec = _tvec.getMat();
if(!((rvec.depth() == CV_32F || rvec.depth() == CV_64F) &&
@@ -656,6 +652,127 @@ void cv::projectPoints( InputArray _objectPoints,
bool calc_derivatives = dpdr.data || dpdt.data || dpdf.data ||
dpdc.data || dpdk.data || dpdo.data;
if (!calc_derivatives)
{
if (objpt_depth == CV_32F && ipoints.type() == CV_32F)
{
float rtMatrix[12] = { (float)R[0], (float)R[1], (float)R[2], (float)t[0],
(float)R[3], (float)R[4], (float)R[5], (float)t[1],
(float)R[6], (float)R[7], (float)R[8], (float)t[2] };
cv_camera_intrinsics_pinhole_32f intr;
intr.fx = (float)fx; intr.fy = (float)fy;
intr.cx = (float)cx; intr.cy = (float)cy;
intr.amt_k = 0; intr.amt_p = 0; intr.amt_s = 0; intr.use_tau = false;
switch (ktotal)
{
case 0: break;
case 4: // [k_1, k_2, p_1, p_2]
intr.amt_k = 2; intr.amt_p = 2;
break;
case 5: // [k_1, k_2, p_1, p_2, k_3]
intr.amt_k = 3; intr.amt_p = 2;
break;
case 8: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6]
intr.amt_k = 6; intr.amt_p = 2;
break;
case 12: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4]
intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4;
break;
case 14: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4, tau_x, tau_y]
intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4; intr.use_tau = true;
break;
default:
CV_Error(cv::Error::StsInternal, "Wrong number of distortion coefficients");
}
intr.k[0] = (float)k[0];
intr.k[1] = (float)k[1];
intr.k[2] = (float)k[4];
intr.k[3] = (float)k[5];
intr.k[4] = (float)k[6];
intr.k[5] = (float)k[7];
intr.p[0] = (float)k[2];
intr.p[1] = (float)k[3];
for (int ctr = 0; ctr < 4; ctr++)
{
intr.s[ctr] = (float)k[8+ctr];
}
intr.tau_x = (float)k[12];
intr.tau_y = (float)k[13];
CALL_HAL(projectPoints, cv_hal_project_points_pinhole32f,
(float*)objectPoints.data, objectPoints.step, count,
(float*)ipoints.data, ipoints.step, rtMatrix, &intr);
}
if (objpt_depth == CV_64F && ipoints.type() == CV_64F)
{
double rtMatrix[12] = { R[0], R[1], R[2], t[0],
R[3], R[4], R[5], t[1],
R[6], R[7], R[8], t[2] };
cv_camera_intrinsics_pinhole_64f intr;
intr.fx = fx; intr.fy = fy;
intr.cx = cx; intr.cy = cy;
intr.amt_k = 0; intr.amt_p = 0; intr.amt_s = 0; intr.use_tau = false;
switch (ktotal)
{
case 0: break;
case 4: // [k_1, k_2, p_1, p_2]
intr.amt_k = 2; intr.amt_p = 2;
break;
case 5: // [k_1, k_2, p_1, p_2, k_3]
intr.amt_k = 3; intr.amt_p = 2;
break;
case 8: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6]
intr.amt_k = 6; intr.amt_p = 2;
break;
case 12: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4]
intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4;
break;
case 14: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4, tau_x, tau_y]
intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4; intr.use_tau = true;
break;
default:
CV_Error(cv::Error::StsInternal, "Wrong number of distortion coefficients");
}
intr.k[0] = k[0];
intr.k[1] = k[1];
intr.k[2] = k[4];
intr.k[3] = k[5];
intr.k[4] = k[6];
intr.k[5] = k[7];
intr.p[0] = k[2];
intr.p[1] = k[3];
for (int ctr = 0; ctr < 4; ctr++)
{
intr.s[ctr] = k[8+ctr];
}
intr.tau_x = k[12];
intr.tau_y = k[13];
CALL_HAL(projectPoints, cv_hal_project_points_pinhole64f,
(double*)objectPoints.data, objectPoints.step, count,
(double*)ipoints.data, ipoints.step, rtMatrix, &intr);
}
}
Mat matM(objectPoints.size(), CV_64FC(objpt_cn));
objectPoints.convertTo(matM, CV_64F);
ipoints.convertTo(_m, CV_64F);
const Point3d* M = matM.ptr<Point3d>();
Point2d* m = _m.ptr<Point2d>();
for( i = 0; i < count; i++ )
{
double X = M[i].x, Y = M[i].y, Z = M[i].z;
+19 -21
View File
@@ -48,6 +48,13 @@
namespace cv {
static inline double scaleFor(double x){
return (std::fabs(x) > std::numeric_limits<float>::epsilon()) ? 1./x : 1.;
}
static inline float scaleFor(float x){
return (std::fabs(x) > std::numeric_limits<float>::epsilon()) ? 1.f/x : 1.f;
}
/**
* This class estimates a homography \f$H\in \mathbb{R}^{3\times 3}\f$
* between \f$\mathbf{x} \in \mathbb{R}^3\f$ and
@@ -176,8 +183,7 @@ public:
eigen( _LtL, matW, matV );
_Htemp = _invHnorm*_H0;
_H0 = _Htemp*_Hnorm2;
_H0.convertTo(_model, _H0.type(), 1./_H0.at<double>(2,2) );
_H0.convertTo(_model, _H0.type(), scaleFor(_H0.at<double>(2,2)));
return 1;
}
@@ -196,14 +202,14 @@ public:
const Point2f* M = m1.ptr<Point2f>();
const Point2f* m = m2.ptr<Point2f>();
const double* H = model.ptr<double>();
float Hf[] = { (float)H[0], (float)H[1], (float)H[2], (float)H[3], (float)H[4], (float)H[5], (float)H[6], (float)H[7] };
float Hf[] = { (float)H[0], (float)H[1], (float)H[2], (float)H[3], (float)H[4], (float)H[5], (float)H[6], (float)H[7], (float)H[8] };
_err.create(count, 1, CV_32F);
float* err = _err.getMat().ptr<float>();
for( i = 0; i < count; i++ )
{
float ww = 1.f/(Hf[6]*M[i].x + Hf[7]*M[i].y + 1.f);
float ww = 1.f/(Hf[6]*M[i].x + Hf[7]*M[i].y + Hf[8]);
float dx = (Hf[0]*M[i].x + Hf[1]*M[i].y + Hf[2])*ww - m[i].x;
float dy = (Hf[3]*M[i].x + Hf[4]*M[i].y + Hf[5])*ww - m[i].y;
err[i] = dx*dx + dy*dy;
@@ -357,7 +363,7 @@ Mat findHomography( InputArray _points1, InputArray _points2,
dst = dst1;
if( method == RANSAC || method == LMEDS )
cb->runKernel( src, dst, H );
Mat H8(8, 1, CV_64F, H.ptr<double>());
Mat H8(9, 1, CV_64F, H.ptr<double>());
auto homographyRefineCallback = [src, dst](InputOutputArray _param, OutputArray _err, OutputArray _Jac) -> bool
{
@@ -368,8 +374,9 @@ Mat findHomography( InputArray _points1, InputArray _points2,
if (_Jac.needed())
{
_Jac.create(count * 2, param.rows, CV_64F);
_Jac.setTo(0.);
J = _Jac.getMat();
CV_Assert(J.isContinuous() && J.cols == 8);
CV_Assert(J.isContinuous() && J.cols == 9);
}
const Point2f* M = src.ptr<Point2f>();
@@ -381,7 +388,7 @@ Mat findHomography( InputArray _points1, InputArray _points2,
for (i = 0; i < count; i++)
{
double Mx = M[i].x, My = M[i].y;
double ww = h[6] * Mx + h[7] * My + 1.;
double ww = h[6] * Mx + h[7] * My + h[8];
ww = fabs(ww) > DBL_EPSILON ? 1. / ww : 0;
double xi = (h[0] * Mx + h[1] * My + h[2]) * ww;
double yi = (h[3] * Mx + h[4] * My + h[5]) * ww;
@@ -391,13 +398,11 @@ Mat findHomography( InputArray _points1, InputArray _points2,
if (Jptr)
{
Jptr[0] = Mx * ww; Jptr[1] = My * ww; Jptr[2] = ww;
Jptr[3] = Jptr[4] = Jptr[5] = 0.;
Jptr[6] = -Mx * ww * xi; Jptr[7] = -My * ww * xi;
Jptr[8] = Jptr[9] = Jptr[10] = 0.;
Jptr[11] = Mx * ww; Jptr[12] = My * ww; Jptr[13] = ww;
Jptr[14] = -Mx * ww * yi; Jptr[15] = -My * ww * yi;
Jptr[6] = -Mx * ww * xi; Jptr[7] = -My * ww * xi; Jptr[8] = -ww * xi;
Jptr[12] = Mx * ww; Jptr[13] = My * ww; Jptr[14] = ww;
Jptr[15] = -Mx * ww * yi; Jptr[16] = -My * ww * yi; Jptr[17] = -ww * yi;
Jptr += 16;
Jptr += 18;
}
}
@@ -408,6 +413,7 @@ Mat findHomography( InputArray _points1, InputArray _points2,
.setMaxIterations(10)
.setGeodesic(true));
solver.optimize();
H.convertTo(H, H.type(), scaleFor(H.at<double>(2, 2)));
}
}
@@ -984,14 +990,6 @@ void computeCorrespondEpilines( InputArray _points, int whichImage,
}
}
static inline double scaleFor(double x){
return (std::fabs(x) > std::numeric_limits<float>::epsilon()) ? 1./x : 1.;
}
static inline float scaleFor(float x){
return (std::fabs(x) > std::numeric_limits<float>::epsilon()) ? 1.f/x : 1.f;
}
void convertPointsFromHomogeneous( InputArray _src, OutputArray _dst, int dtype )
{
CV_INSTRUMENT_REGION();
+188
View File
@@ -0,0 +1,188 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Copyright (C) 2015, Itseez Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_CALIB3D_HAL_REPLACEMENT_HPP
#define OPENCV_CALIB3D_HAL_REPLACEMENT_HPP
#include "opencv2/core/hal/interface.h"
#if defined(__clang__) // clang or MSVC clang
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4100)
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
//! @addtogroup calib3d_hal_interface
//! @note Define your functions to override default implementations:
//! @code
//! #undef hal_add8u
//! #define hal_add8u my_add8u
//! @endcode
//! @{
/**
* @brief Camera intrinsics structure, see projectPoints() documentation for details
*/
struct cv_camera_intrinsics_pinhole_32f
{
// focal length, principal point
float fx, fy, cx, cy;
// radial distortion coefficients
float k[6];
// amount of radial distortion coefficients passed
int amt_k;
// tangential distortion coefficients
float p[2];
// amount of tangential distortion coefficients passed
int amt_p;
// prism distortion coefficients
float s[4];
// amount of prism distortion coefficients passed
int amt_s;
// tilt distortion coefficients
float tau_x, tau_y;
// to use tilt distortion coefficients or not
bool use_tau;
};
/**
@brief Project points from 3D world space to 2D screen space using rotation and translation matrix and camera intrinsic parameters
@param src_data Pointer to 3D points array with coordinates interleaved as X, Y, Z, X, Y, Z,..
@param src_step Step between consecutive 3D points
@param src_size Amount of points
@param dst_data Pointer to resulting projected 2D points with coordinates interleaved as u, v, u, v,..
@param dst_step Step between consecutive projected 2D points
@param rt_data Pointer to 3x4 array containing rotation-then-translation matrix
@param intr_data Pointer to camera intrinsics structure
*/
inline int hal_ni_project_points_pinhole32f(const float* src_data, size_t src_step, size_t src_size,
float* dst_data, size_t dst_step, const float* rt_data,
const cv_camera_intrinsics_pinhole_32f* intr_data)
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_project_points_pinhole32f hal_ni_project_points_pinhole32f
//! @endcond
/**
* @brief Camera intrinsics structure, see projectPoints() documentation for details
*/
struct cv_camera_intrinsics_pinhole_64f
{
// focal length, principal point
double fx, fy, cx, cy;
// radial distortion coefficients
double k[6];
// amount of radial distortion coefficients passed
int amt_k;
// tangential distortion coefficients
double p[2];
// amount of tangential distortion coefficients passed
int amt_p;
// prism distortion coefficients
double s[4];
// amount of prism distortion coefficients passed
int amt_s;
// tilt distortion coefficients
double tau_x, tau_y;
// to use tilt distortion coefficients or not
bool use_tau;
};
/**
@brief Project points from 3D world space to 2D screen space using rotation and translation matrix and camera intrinsic parameters
@param src_data Pointer to 3D points array with coordinates interleaved as X, Y, Z, X, Y, Z,..
@param src_step Step between consecutive 3D points
@param src_size Amount of points
@param dst_data Pointer to resulting projected 2D points with coordinates interleaved as u, v, u, v,..
@param dst_step Step between consecutive projected 2D points
@param rt_data Pointer to 3x4 array containing rotation-then-translation matrix
@param intr_data Pointer to camera intrinsics structure
*/
inline int hal_ni_project_points_pinhole64f(const double* src_data, size_t src_step, size_t src_size,
double* dst_data, size_t dst_step, const double* rt_data,
const cv_camera_intrinsics_pinhole_64f* intr_data)
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_project_points_pinhole64f hal_ni_project_points_pinhole64f
//! @endcond
//! @}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#include "custom_hal.hpp"
//! @cond IGNORED
#define CALL_HAL_RET(name, fun, retval, ...) \
int res = __CV_EXPAND(fun(__VA_ARGS__, &retval)); \
if (res == CV_HAL_ERROR_OK) \
return retval; \
else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \
CV_Error_(cv::Error::StsInternal, \
("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res));
#define CALL_HAL(name, fun, ...) \
int res = __CV_EXPAND(fun(__VA_ARGS__)); \
if (res == CV_HAL_ERROR_OK) \
return; \
else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \
CV_Error_(cv::Error::StsInternal, \
("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res));
//! @endcond
#endif
+5
View File
@@ -155,7 +155,12 @@ public:
const auto &eigen_vectors = eigen_solver.eigenvectors();
const auto &eigen_values = eigen_solver.eigenvalues();
#else
#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64)
long mat_order = 27, info, lda = 27, ldvl = 1, ldvr = 27, lwork = 500;
#else
int mat_order = 27, info, lda = 27, ldvl = 1, ldvr = 27, lwork = 500;
#endif
double wr[27], wi[27] = {0}; // 27 = mat_order
std::vector<double> work(lwork), eig_vecs(729);
char jobvl = 'N', jobvr = 'V'; // only left eigen vectors are computed
+4
View File
@@ -259,7 +259,11 @@ public:
action_mat_data[83] = -1.0; // 8 row, 3 col
action_mat_data[96] = -1.0; // 9 row, 6 col
#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64)
long mat_order = 10, info, lda = 10, ldvl = 10, ldvr = 1, lwork = 100;
#else
int mat_order = 10, info, lda = 10, ldvl = 10, ldvr = 1, lwork = 100;
#endif
double wr[10], wi[10] = {0}, eig_vecs[100], work[100]; // 10 = mat_order, 100 = lwork
char jobvl = 'V', jobvr = 'N'; // only left eigen vectors are computed
OCV_LAPACK_FUNC(dgeev)(&jobvl, &jobvr, &mat_order, action_mat_data, &lda, wr, wi, eig_vecs, &ldvl,
+59
View File
@@ -705,4 +705,63 @@ TEST(Calib3d_Homography, minPoints)
EXPECT_THROW(findHomography(p1, p2, RANSAC, 0.01, mask), cv::Exception);
}
TEST(Calib3d_Homography, not_normalized)
{
Mat_<double> p1({5, 2}, {-1, -1, -2, -2, -1, 1, -2, 2, -1, 0});
Mat_<double> p2({5, 2}, {0, -1, -1, -1, 0, 0, -1, 0, 0, -0.5});
Mat_<double> ref({3, 3}, {
0.74276086, 0., 0.74276086,
0.18569022, 0.18569022, 0.,
-0.37138043, 0., 0.
});
for (int method : std::vector<int>({0, RANSAC, LMEDS}))
{
Mat h = findHomography(p1, p2, method);
for (auto it = h.begin<double>(); it != h.end<double>(); ++it) {
ASSERT_FALSE(cvIsNaN(*it)) << cv::format("method %d\nResult:\n", method) << h;
}
if (h.at<double>(0, 0) * ref.at<double>(0, 0) < 0) {
h *= -1;
}
ASSERT_LE(cv::norm(h, ref, NORM_INF), 1e-8) << cv::format("method %d\nResult:\n", method) << h;
}
}
TEST(Calib3d_Homography, Refine)
{
Mat_<double> p1({10, 2}, {41, -86, -87, 99, 66, -96, -86, -8, -67, 24,
-87, -76, -19, 89, 37, -4, -86, -86, -66, -53});
Mat_<double> p2({10, 2}, {
0.007723226608700208, -1.177541410622515,
-0.1909072353027552, -0.4247610181930323,
-0.134992319993638, -0.6469949816560389,
-0.3570627451405215, 0.1811469436293486,
-0.3005671881038939, -0.02325733734262935,
-0.4404509481789249, 0.4851526464158342,
0.6343346428859541, -3.396187657072353,
-0.3539383967092603, 0.1469447227353143,
-0.4526924606856586, 0.5296757109061794,
-0.4309974583614644, 0.4522732662733471
});
hconcat(p1, Mat::ones(p1.rows, 1, CV_64F), p1);
hconcat(p2, Mat::ones(p2.rows, 1, CV_64F), p2);
for(int method : std::vector<int>({0, RANSAC, LMEDS}))
{
Mat h = findHomography(p1, p2, method);
EXPECT_NEAR(h.at<double>(2, 2), 1.0, 1e-7);
Mat proj = p1 * h.t();
proj.col(0) /= proj.col(2);
proj.col(1) /= proj.col(2);
Mat error;
cv::pow(p2.colRange(0, 2) - proj.colRange(0, 2), 2, error);
cv::reduce(error, error, 1, REDUCE_SUM);
cv::reduce(error, error, 0, REDUCE_AVG);
EXPECT_LE(sqrt(error.at<double>(0, 0)), method == LMEDS ? 7e-2 : 7e-5);
}
}
}} // namespace