Commit ee79c1f4 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #988 from sovrasov:reg_python_bindings

parents d879ea48 17c45536
......@@ -121,13 +121,13 @@ namespace reg {
The class is only used to define the common interface for any possible map.
*/
class CV_EXPORTS Map
class CV_EXPORTS_W Map
{
public:
/*!
* Virtual destructor
*/
virtual ~Map(void);
virtual ~Map();
/*!
* Warps image to a new coordinate frame. The calculation is img2(x)=img1(T^{-1}(x)), as we
......@@ -136,7 +136,7 @@ public:
* \param[in] img1 Original image
* \param[out] img2 Warped image
*/
virtual void warp(const cv::Mat& img1, cv::Mat& img2) const;
CV_WRAP virtual void warp(InputArray img1, OutputArray img2) const;
/*!
* Warps image to a new coordinate frame. The calculation is img2(x)=img1(T(x)), so in fact
......@@ -145,27 +145,27 @@ public:
* \param[in] img1 Original image
* \param[out] img2 Warped image
*/
virtual void inverseWarp(const cv::Mat& img1, cv::Mat& img2) const = 0;
CV_WRAP virtual void inverseWarp(InputArray img1, OutputArray img2) const = 0;
/*!
* Calculates the inverse map
* \return Inverse map
*/
virtual cv::Ptr<Map> inverseMap(void) const = 0;
CV_WRAP virtual cv::Ptr<Map> inverseMap() const = 0;
/*!
* Changes the map composing the current transformation with the one provided in the call.
* The order is first the current transformation, then the input argument.
* \param[in] map Transformation to compose with.
*/
virtual void compose(const Map& map) = 0;
CV_WRAP virtual void compose(cv::Ptr<Map> map) = 0;
/*!
* Scales the map by a given factor as if the coordinates system is expanded/compressed
* by that factor.
* \param[in] factor Expansion if bigger than one, compression if smaller than one
*/
virtual void scale(double factor) = 0;
CV_WRAP virtual void scale(double factor) = 0;
};
//! @}
......
......@@ -49,13 +49,13 @@ namespace reg {
/*!
* Defines an affine transformation
*/
class CV_EXPORTS MapAffine : public Map
class CV_EXPORTS_W MapAffine : public Map
{
public:
/*!
* Default constructor builds an identity map
*/
MapAffine(void);
CV_WRAP MapAffine();
/*!
* Constructor providing explicit values
......@@ -67,15 +67,15 @@ public:
/*!
* Destructor
*/
~MapAffine(void);
~MapAffine();
void inverseWarp(const cv::Mat& img1, cv::Mat& img2) const;
CV_WRAP void inverseWarp(InputArray img1, OutputArray img2) const;
cv::Ptr<Map> inverseMap(void) const;
CV_WRAP cv::Ptr<Map> inverseMap() const;
void compose(const Map& map);
CV_WRAP void compose(cv::Ptr<Map> map);
void scale(double factor);
CV_WRAP void scale(double factor);
/*!
* Return linear part of the affine transformation
......@@ -85,6 +85,10 @@ public:
return linTr_;
}
CV_WRAP void getLinTr(OutputArray linTr) const {
Mat(linTr_).copyTo(linTr);
}
/*!
* Return displacement part of the affine transformation
* \return Displacement part of the affine transformation
......@@ -93,6 +97,10 @@ public:
return shift_;
}
CV_WRAP void getShift(OutputArray shift) const {
Mat(shift_).copyTo(shift);
}
private:
cv::Matx<double, 2, 2> linTr_;
cv::Vec<double, 2> shift_;
......
......@@ -47,11 +47,11 @@ namespace reg {
//! @addtogroup reg
//! @{
/** @brief Base class for modelling an algorithm for calculating a
/** @brief Base class for modelling an algorithm for calculating a map
The class is only used to define the common interface for any possible mapping algorithm.
*/
class CV_EXPORTS Mapper
class CV_EXPORTS_W Mapper
{
public:
virtual ~Mapper(void) {}
......@@ -60,16 +60,16 @@ public:
* Calculate mapping between two images
* \param[in] img1 Reference image
* \param[in] img2 Warped image
* \param[in,out] res Map from img1 to img2, stored in a smart pointer. If present as input,
* it is an initial rough estimation that the mapper will try to refine.
* \param[in] If present, it is an initial rough estimation that the mapper will try to refine.
* \return Map from img1 to img2, stored in a smart pointer.
*/
virtual void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const = 0;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const = 0;
/*
* Returns a map compatible with the Mapper class
* \return Pointer to identity Map
*/
virtual cv::Ptr<Map> getMap(void) const = 0;
CV_WRAP virtual cv::Ptr<Map> getMap() const = 0;
protected:
/*
......
......@@ -49,15 +49,15 @@ namespace reg {
/*!
* Mapper for affine motion
*/
class CV_EXPORTS MapperGradAffine: public Mapper
class CV_EXPORTS_W MapperGradAffine: public Mapper
{
public:
MapperGradAffine(void);
CV_WRAP MapperGradAffine();
~MapperGradAffine(void);
virtual void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const;
cv::Ptr<Map> getMap(void) const;
CV_WRAP cv::Ptr<Map> getMap() const;
};
//! @}
......
......@@ -49,15 +49,15 @@ namespace reg {
/*!
* Mapper for euclidean motion: rotation plus shift
*/
class CV_EXPORTS MapperGradEuclid: public Mapper
class CV_EXPORTS_W MapperGradEuclid: public Mapper
{
public:
MapperGradEuclid(void);
~MapperGradEuclid(void);
CV_WRAP MapperGradEuclid();
~MapperGradEuclid();
virtual void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const;
cv::Ptr<Map> getMap(void) const;
CV_WRAP cv::Ptr<Map> getMap() const;
};
//! @}
......
......@@ -49,15 +49,15 @@ namespace reg {
/*!
* Gradient mapper for a projective transformation
*/
class CV_EXPORTS MapperGradProj: public Mapper
class CV_EXPORTS_W MapperGradProj: public Mapper
{
public:
MapperGradProj(void);
~MapperGradProj(void);
CV_WRAP MapperGradProj();
~MapperGradProj();
virtual void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const;
cv::Ptr<Map> getMap(void) const;
CV_WRAP cv::Ptr<Map> getMap() const;
};
//! @}
......
......@@ -49,15 +49,15 @@ namespace reg {
/*!
* Gradient mapper for a translation
*/
class CV_EXPORTS MapperGradShift: public Mapper
class CV_EXPORTS_W MapperGradShift: public Mapper
{
public:
MapperGradShift(void);
virtual ~MapperGradShift(void);
CV_WRAP MapperGradShift();
virtual ~MapperGradShift();
virtual void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const;
cv::Ptr<Map> getMap(void) const;
CV_WRAP cv::Ptr<Map> getMap() const;
};
//! @}
......
......@@ -49,15 +49,15 @@ namespace reg {
/*!
* Calculates a similarity transformation between to images (scale, rotation, and shift)
*/
class CV_EXPORTS MapperGradSimilar: public Mapper
class CV_EXPORTS_W MapperGradSimilar: public Mapper
{
public:
MapperGradSimilar(void);
~MapperGradSimilar(void);
CV_WRAP MapperGradSimilar();
~MapperGradSimilar();
virtual void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const;
cv::Ptr<Map> getMap(void) const;
CV_WRAP cv::Ptr<Map> getMap() const;
};
//! @}
......
......@@ -39,7 +39,9 @@
#define MAPPERPYRAMID_H_
#include "mapper.hpp"
#include "mapaffine.hpp"
#include "mapprojec.hpp"
#include "mapshift.hpp"
namespace cv {
namespace reg {
......@@ -50,27 +52,52 @@ namespace reg {
/*!
* Calculates a map using a gaussian pyramid
*/
class CV_EXPORTS MapperPyramid: public Mapper
class CV_EXPORTS_W MapperPyramid: public Mapper
{
public:
/*
* Constructor
* \param[in] baseMapper Base mapper used for the refinements
*/
MapperPyramid(const Mapper& baseMapper);
CV_WRAP MapperPyramid(Ptr<Mapper> baseMapper);
void calculate(const cv::Mat& img1, const cv::Mat& img2, cv::Ptr<Map>& res) const;
CV_WRAP virtual cv::Ptr<Map> calculate(InputArray img1, InputArray img2, cv::Ptr<Map> init = cv::Ptr<Map>()) const;
cv::Ptr<Map> getMap(void) const;
CV_WRAP cv::Ptr<Map> getMap() const;
unsigned numLev_; /*!< Number of levels of the pyramid */
unsigned numIterPerScale_; /*!< Number of iterations at a given scale of the pyramid */
CV_PROP_RW int numLev_; /*!< Number of levels of the pyramid */
CV_PROP_RW int numIterPerScale_; /*!< Number of iterations at a given scale of the pyramid */
private:
MapperPyramid& operator=(const MapperPyramid&);
const Mapper& baseMapper_; /*!< Mapper used in inner level */
};
/*!
* Converts a pointer to a Map returned by MapperPyramid::calculate into the specified Map pointer type
*/
class CV_EXPORTS_W MapTypeCaster
{
public:
CV_WRAP static Ptr<MapAffine> toAffine(Ptr<Map> sourceMap)
{
MapAffine& affineMap = dynamic_cast<MapAffine&>(*sourceMap);
return Ptr<MapAffine>(new MapAffine(affineMap));
}
CV_WRAP static Ptr<MapShift> toShift(Ptr<Map> sourceMap)
{
MapShift& shiftMap = dynamic_cast<MapShift&>(*sourceMap);
return Ptr<MapShift>(new MapShift(shiftMap));
}
CV_WRAP static Ptr<MapProjec> toProjec(Ptr<Map> sourceMap)
{
MapProjec& projecMap = dynamic_cast<MapProjec&>(*sourceMap);
return Ptr<MapProjec>(new MapProjec(projecMap));
}
};
//! @}
}} // namespace cv::reg
......
......@@ -50,13 +50,13 @@ namespace reg {
/*!
* Defines an transformation that consists on a projective transformation
*/
class CV_EXPORTS MapProjec : public Map
class CV_EXPORTS_W MapProjec : public Map
{
public:
/*!
* Default constructor builds an identity map
*/
MapProjec(void);
CV_WRAP MapProjec();
/*!
* Constructor providing explicit values
......@@ -67,15 +67,15 @@ public:
/*!
* Destructor
*/
~MapProjec(void);
~MapProjec();
void inverseWarp(const cv::Mat& img1, cv::Mat& img2) const;
CV_WRAP void inverseWarp(InputArray img1, OutputArray img2) const;
cv::Ptr<Map> inverseMap(void) const;
CV_WRAP cv::Ptr<Map> inverseMap() const;
void compose(const Map& map);
CV_WRAP void compose(cv::Ptr<Map> map);
void scale(double factor);
CV_WRAP void scale(double factor);
/*!
* Returns projection matrix
......@@ -85,10 +85,14 @@ public:
return projTr_;
}
CV_WRAP void getProjTr(OutputArray projTr) const {
Mat(projTr_).copyTo(projTr);
}
/*!
* Normalizes object's homography
*/
void normalize(void) {
CV_WRAP void normalize() {
double z = 1./projTr_(2, 2);
for(size_t v_i = 0; v_i < sizeof(projTr_.val)/sizeof(projTr_.val[0]); ++v_i)
projTr_.val[v_i] *= z;
......
......@@ -50,32 +50,33 @@ namespace reg {
/*!
* Defines an transformation that consists on a simple displacement
*/
class CV_EXPORTS MapShift : public Map
class CV_EXPORTS_W MapShift : public Map
{
public:
/*!
* Default constructor builds an identity map
*/
MapShift(void);
CV_WRAP MapShift();
/*!
* Constructor providing explicit values
* \param[in] shift Displacement
*/
MapShift(const cv::Vec<double, 2>& shift);
CV_WRAP MapShift(InputArray shift);
/*!
* Destructor
*/
~MapShift(void);
~MapShift();
void inverseWarp(const cv::Mat& img1, cv::Mat& img2) const;
CV_WRAP void inverseWarp(InputArray img1, OutputArray img2) const;
cv::Ptr<Map> inverseMap(void) const;
CV_WRAP cv::Ptr<Map> inverseMap() const;
void compose(const Map& map);
CV_WRAP void compose(cv::Ptr<Map> map);
void scale(double factor);
CV_WRAP void scale(double factor);
/*!
* Return displacement
......@@ -85,6 +86,10 @@ public:
return shift_;
}
CV_WRAP void getShift(OutputArray shift) const {
Mat(shift_).copyTo(shift);
}
private:
cv::Vec<double, 2> shift_; /*< Displacement */
};
......
......@@ -72,10 +72,9 @@ Vec<double, 2> perfShift(const Mat& img1)
mapTest.warp(img1, img2);
// Register
MapperGradShift mapper;
Ptr<MapperGradShift> mapper = makePtr<MapperGradShift>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
MapShift* mapShift = dynamic_cast<MapShift*>(mapPtr.get());
return mapShift->getShift();
......@@ -96,10 +95,9 @@ Matx<double, 2, 6> perfEuclidean(const Mat& img1)
mapTest.warp(img1, img2);
// Register
MapperGradEuclid mapper;
Ptr<MapperGradEuclid> mapper = makePtr<MapperGradEuclid>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
Matx<double, 2, 2> resLinTr = mapAff->getLinTr();
......@@ -127,10 +125,9 @@ Matx<double, 2, 6> perfSimilarity(const Mat& img1)
mapTest.warp(img1, img2);
// Register
MapperGradSimilar mapper;
Ptr<MapperGradSimilar> mapper = makePtr<MapperGradSimilar>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
Matx<double, 2, 2> resLinTr = mapAff->getLinTr();
......@@ -154,10 +151,9 @@ Matx<double, 2, 6> perfAffine(const Mat& img1)
mapTest.warp(img1, img2);
// Register
MapperGradAffine mapper;
Ptr<MapperGradAffine> mapper = makePtr<MapperGradAffine>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
Matx<double, 2, 2> resLinTr = mapAff->getLinTr();
......@@ -179,10 +175,9 @@ Matx<double, 3, 3> perfProjective(const Mat& img1)
mapTest.warp(img1, img2);
// Register
MapperGradProj mapper;
Ptr<MapperGradProj> mapper = makePtr<MapperGradProj>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
MapProjec* mapProj = dynamic_cast<MapProjec*>(mapPtr.get());
mapProj->normalize();
......
......@@ -99,10 +99,9 @@ static void testShift(const Mat& img1)
showDifference(img1, img2, DIFF_IM);
// Register
MapperGradShift mapper;
Ptr<MapperGradShift> mapper = makePtr<MapperGradShift>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapShift* mapShift = dynamic_cast<MapShift*>(mapPtr.get());
......@@ -135,10 +134,9 @@ static void testEuclidean(const Mat& img1)
showDifference(img1, img2, DIFF_IM);
// Register
MapperGradEuclid mapper;
Ptr<MapperGradEuclid> mapper = makePtr<MapperGradEuclid>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
......@@ -174,10 +172,9 @@ static void testSimilarity(const Mat& img1)
showDifference(img1, img2, DIFF_IM);
// Register
MapperGradSimilar mapper;
Ptr<MapperGradSimilar> mapper = makePtr<MapperGradSimilar>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
......@@ -209,10 +206,9 @@ static void testAffine(const Mat& img1)
showDifference(img1, img2, DIFF_IM);
// Register
MapperGradAffine mapper;
Ptr<MapperGradAffine> mapper = makePtr<MapperGradAffine>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
......@@ -243,10 +239,9 @@ static void testProjective(const Mat& img1)
showDifference(img1, img2, DIFF_IM);
// Register
MapperGradProj mapper;
Ptr<MapperGradProj> mapper = makePtr<MapperGradProj>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapProjec* mapProj = dynamic_cast<MapProjec*>(mapPtr.get());
......@@ -347,7 +342,7 @@ static void calcHomographyFeature(const Mat& image1, const Mat& image2)
warpPerspective(image2, result, Hinv, image1.size());
cout << "--- Feature method\n" << H << endl;
Mat imf1, resf;
image1.convertTo(imf1, CV_64FC3);
result.convertTo(resf, CV_64FC3);
......@@ -359,10 +354,9 @@ static void calcHomographyPixel(const Mat& img1, const Mat& img2)
static const char* diffpixel = "Difference pixel registered";
// Register using pixel differences
MapperGradProj mapper;
Ptr<MapperGradProj> mapper = makePtr<MapperGradProj>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapProjec* mapProj = dynamic_cast<MapProjec*>(mapPtr.get());
......@@ -398,7 +392,7 @@ static void comparePixelVsFeature(const Mat& img1_8b, const Mat& img2_8b)
int main(void)
{
Mat img1;
Mat img1;
img1 = imread("home.png", CV_LOAD_IMAGE_UNCHANGED);
if(!img1.data) {
cout << "Could not open or find file" << endl;
......
#!/usr/bin/python
import cv2
import numpy as np
import sys
img1 = cv2.imread(sys.argv[1])
img1 = img1.astype(np.float32)
shift = np.array([5., 5.])
mapTest = cv2.reg.MapShift(shift)
img2 = mapTest.warp(img1)
mapper = cv2.reg.MapperGradShift()
mappPyr = cv2.reg.MapperPyramid(mapper)
resMap = mappPyr.calculate(img1, img2)
mapShift = cv2.reg.MapTypeCaster_toShift(resMap)
print(mapShift.getShift())
......@@ -44,12 +44,12 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
Map::~Map(void)
Map::~Map()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Map::warp(const Mat& img1, Mat& img2) const
void Map::warp(InputArray img1, OutputArray img2) const
{
Ptr<Map> invMap(inverseMap());
invMap->inverseWarp(img1, img2);
......
......@@ -45,7 +45,7 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapAffine::MapAffine(void)
MapAffine::MapAffine()
: linTr_(Matx<double, 2, 2>::eye()), shift_()
{
}
......@@ -57,13 +57,14 @@ MapAffine::MapAffine(const Matx<double, 2, 2>& linTr, const Vec<double, 2>& shif
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapAffine::~MapAffine(void)
MapAffine::~MapAffine()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapAffine::inverseWarp(const Mat& img1, Mat& img2) const
void MapAffine::inverseWarp(InputArray _img1, OutputArray img2) const
{
Mat img1 = _img1.getMat();
// Rows and columns in destination
Mat dest_r, dest_c;
dest_r.create(img1.size(), CV_32FC1);
......@@ -93,10 +94,10 @@ Ptr<Map> MapAffine::inverseMap(void) const
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapAffine::compose(const Map& map)
void MapAffine::compose(cv::Ptr<Map> map)
{
// Composition of affine transformations T and T' is (T o T') = A'Ax + A'b + b'
const MapAffine& mapAff = static_cast<const MapAffine&>(map);
const MapAffine& mapAff = static_cast<const MapAffine&>(*map);
Matx<double, 2, 2> compMat = mapAff.getLinTr()*linTr_;
Vec<double, 2> compShift = mapAff.getLinTr()*shift_ + mapAff.getShift();
linTr_ = compMat;
......
......@@ -59,28 +59,45 @@ void Mapper::gradient(const Mat& img1, const Mat& img2, Mat& Ix, Mat& Iy, Mat& I
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Mapper::grid(const Mat& img, Mat& grid_r, Mat& grid_c) const
template<typename _Tp>
void fillGridMatrices(const Mat img, Mat grid_r, Mat grid_c)
{
// Matrices with reference frame coordinates
grid_r.create(img.size(), img.type());
grid_c.create(img.size(), img.type());
if(img.channels() == 1) {
for(int r_i = 0; r_i < img.rows; ++r_i) {
for(int c_i = 0; c_i < img.cols; ++c_i) {
grid_r.at<double>(r_i, c_i) = r_i;
grid_c.at<double>(r_i, c_i) = c_i;
grid_r.at<_Tp>(r_i, c_i) = (_Tp)r_i;
grid_c.at<_Tp>(r_i, c_i) = (_Tp)c_i;
}
}
} else {
Vec3d ones(1., 1., 1.);
Vec<_Tp, 3> ones((_Tp)1, (_Tp)1, (_Tp)1);
for(int r_i = 0; r_i < img.rows; ++r_i) {
for(int c_i = 0; c_i < img.cols; ++c_i) {
grid_r.at<Vec3d>(r_i, c_i) = r_i*ones;
grid_c.at<Vec3d>(r_i, c_i) = c_i*ones;
grid_r.at< Vec<_Tp, 3> >(r_i, c_i) = (_Tp)r_i*ones;
grid_c.at< Vec<_Tp, 3> >(r_i, c_i) = (_Tp)c_i*ones;
}
}
}
}
void Mapper::grid(const Mat& img, Mat& grid_r, Mat& grid_c) const
{
CV_DbgAssert(img.channels() == 1 || img.channels() == 3);
// Matrices with reference frame coordinates
grid_r.create(img.size(), img.type());
grid_c.create(img.size(), img.type());
if(img.depth() == CV_8U)
fillGridMatrices<uchar>(img, grid_r, grid_c);
if(img.depth() == CV_16U)
fillGridMatrices<ushort>(img, grid_r, grid_c);
else if(img.depth() == CV_32F)
fillGridMatrices<float>(img, grid_r, grid_c);
else if(img.depth() == CV_64F)
fillGridMatrices<double>(img, grid_r, grid_c);
}
}} // namespace cv::reg
......@@ -44,21 +44,21 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradAffine::MapperGradAffine(void)
MapperGradAffine::MapperGradAffine()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradAffine::~MapperGradAffine(void)
MapperGradAffine::~MapperGradAffine()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapperGradAffine::calculate(
const cv::Mat& img1, const cv::Mat& image2, cv::Ptr<Map>& res) const
cv::Ptr<Map> MapperGradAffine::calculate(InputArray _img1, InputArray image2, cv::Ptr<Map> init) const
{
Mat img1 = _img1.getMat();
Mat gradx, grady, imgDiff;
Mat img2;
......@@ -66,11 +66,11 @@ void MapperGradAffine::calculate(
CV_DbgAssert(img1.channels() == image2.channels());
CV_DbgAssert(img1.channels() == 1 || img1.channels() == 3);
if(!res.empty()) {
if(!init.empty()) {
// We have initial values for the registration: we move img2 to that initial reference
res->inverseWarp(image2, img2);
init->inverseWarp(image2, img2);
} else {
img2 = image2;
img2 = image2.getMat();
}
// Get gradient in all channels
......@@ -145,16 +145,19 @@ void MapperGradAffine::calculate(
Matx<double, 2, 2> linTr(k(0) + 1., k(1), k(3), k(4) + 1.);
Vec<double, 2> shift(k(2), k(5));
if(res.empty()) {
res = Ptr<Map>(new MapAffine(linTr, shift));
if(init.empty()) {
return Ptr<Map>(new MapAffine(linTr, shift));
} else {
MapAffine newTr(linTr, shift);
res->compose(newTr);
Ptr<MapAffine> newTr(new MapAffine(linTr, shift));
MapAffine* initPtr = dynamic_cast<MapAffine*>(init.get());
Ptr<MapAffine> oldTr(new MapAffine(initPtr->getLinTr(), initPtr->getShift()));
oldTr->compose(newTr);
return oldTr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
cv::Ptr<Map> MapperGradAffine::getMap(void) const
cv::Ptr<Map> MapperGradAffine::getMap() const
{
return cv::Ptr<Map>(new MapAffine());
}
......
......@@ -44,21 +44,22 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradEuclid::MapperGradEuclid(void)
MapperGradEuclid::MapperGradEuclid()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradEuclid::~MapperGradEuclid(void)
MapperGradEuclid::~MapperGradEuclid()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapperGradEuclid::calculate(
const cv::Mat& img1, const cv::Mat& image2, cv::Ptr<Map>& res) const
cv::Ptr<Map> MapperGradEuclid::calculate(
InputArray _img1, InputArray image2, cv::Ptr<Map> init) const
{
Mat img1 = _img1.getMat();
Mat gradx, grady, imgDiff;
Mat img2;
......@@ -66,11 +67,11 @@ void MapperGradEuclid::calculate(
CV_DbgAssert(img1.channels() == image2.channels());
CV_DbgAssert(img1.channels() == 1 || img1.channels() == 3);
if(!res.empty()) {
if(!init.empty()) {
// We have initial values for the registration: we move img2 to that initial reference
res->inverseWarp(image2, img2);
init->inverseWarp(image2, img2);
} else {
img2 = image2;
img2 = image2.getMat();
}
// Matrices with reference frame coordinates
......@@ -111,16 +112,19 @@ void MapperGradEuclid::calculate(
Matx<double, 2, 2> linTr(cosT, -sinT, sinT, cosT);
Vec<double, 2> shift(k(0), k(1));
if(res.empty()) {
res = Ptr<Map>(new MapAffine(linTr, shift));
if(init.empty()) {
return Ptr<Map>(new MapAffine(linTr, shift));
} else {
MapAffine newTr(linTr, shift);
res->compose(newTr);
Ptr<MapAffine> newTr(new MapAffine(linTr, shift));
MapAffine* initPtr = dynamic_cast<MapAffine*>(init.get());
Ptr<MapAffine> oldTr(new MapAffine(initPtr->getLinTr(), initPtr->getShift()));
oldTr->compose(newTr);
return oldTr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
cv::Ptr<Map> MapperGradEuclid::getMap(void) const
cv::Ptr<Map> MapperGradEuclid::getMap() const
{
return cv::Ptr<Map>(new MapAffine());
}
......
......@@ -44,21 +44,22 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradProj::MapperGradProj(void)
MapperGradProj::MapperGradProj()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradProj::~MapperGradProj(void)
MapperGradProj::~MapperGradProj()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapperGradProj::calculate(
const cv::Mat& img1, const cv::Mat& image2, cv::Ptr<Map>& res) const
cv::Ptr<Map> MapperGradProj::calculate(
InputArray _img1, InputArray image2, cv::Ptr<Map> init) const
{
Mat img1 = _img1.getMat();
Mat gradx, grady, imgDiff;
Mat img2;
......@@ -66,11 +67,11 @@ void MapperGradProj::calculate(
CV_DbgAssert(img1.channels() == image2.channels());
CV_DbgAssert(img1.channels() == 1 || img1.channels() == 3);
if(!res.empty()) {
if(!init.empty()) {
// We have initial values for the registration: we move img2 to that initial reference
res->inverseWarp(image2, img2);
init->inverseWarp(image2, img2);
} else {
img2 = image2;
img2 = image2.getMat();
}
// Get gradient in all channels
......@@ -195,16 +196,19 @@ void MapperGradProj::calculate(
Vec<double, 8> k = A.inv(DECOMP_CHOLESKY)*b;
Matx<double, 3, 3> H(k(0) + 1., k(1), k(2), k(3), k(4) + 1., k(5), k(6), k(7), 1.);
if(res.empty()) {
res = Ptr<Map>(new MapProjec(H));
if(init.empty()) {
return Ptr<Map>(new MapProjec(H));
} else {
MapProjec newTr(H);
res->compose(newTr);
Ptr<MapProjec> newTr(new MapProjec(H));
MapProjec* initPtr = dynamic_cast<MapProjec*>(init.get());
Ptr<MapProjec> oldTr(new MapProjec(initPtr->getProjTr()));
oldTr->compose(newTr);
return oldTr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
cv::Ptr<Map> MapperGradProj::getMap(void) const
cv::Ptr<Map> MapperGradProj::getMap() const
{
return cv::Ptr<Map>(new MapProjec());
}
......
......@@ -44,31 +44,32 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradShift::MapperGradShift(void)
MapperGradShift::MapperGradShift()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradShift::~MapperGradShift(void)
MapperGradShift::~MapperGradShift()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapperGradShift::calculate(
const cv::Mat& img1, const cv::Mat& image2, cv::Ptr<Map>& res) const
cv::Ptr<Map> MapperGradShift::calculate(
InputArray _img1, InputArray image2, cv::Ptr<Map> init) const
{
Mat img1 = _img1.getMat();
Mat gradx, grady, imgDiff;
Mat img2;
CV_DbgAssert(img1.size() == image2.size());
if(!res.empty()) {
if(!init.empty()) {
// We have initial values for the registration: we move img2 to that initial reference
res->inverseWarp(image2, img2);
init->inverseWarp(image2, img2);
} else {
img2 = image2;
img2 = image2.getMat();
}
// Get gradient in all channels
......@@ -92,16 +93,19 @@ void MapperGradShift::calculate(
// Calculate shift. We use Cholesky decomposition, as A is symmetric.
Vec<double, 2> shift = A.inv(DECOMP_CHOLESKY)*b;
if(res.empty()) {
res = Ptr<Map>(new MapShift(shift));
if(init.empty()) {
return Ptr<Map>(new MapShift(shift));
} else {
MapShift newTr(shift);
res->compose(newTr);
Ptr<MapShift> newTr(new MapShift(shift));
MapShift* initPtr = dynamic_cast<MapShift*>(init.get());
Ptr<MapShift> oldTr(new MapShift(initPtr->getShift()));
oldTr->compose(newTr);
return oldTr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
cv::Ptr<Map> MapperGradShift::getMap(void) const
cv::Ptr<Map> MapperGradShift::getMap() const
{
return cv::Ptr<Map>(new MapShift());
}
......
......@@ -44,21 +44,22 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradSimilar::MapperGradSimilar(void)
MapperGradSimilar::MapperGradSimilar()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperGradSimilar::~MapperGradSimilar(void)
MapperGradSimilar::~MapperGradSimilar()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapperGradSimilar::calculate(
const cv::Mat& img1, const cv::Mat& image2, cv::Ptr<Map>& res) const
cv::Ptr<Map> MapperGradSimilar::calculate(
InputArray _img1, InputArray image2, cv::Ptr<Map> init) const
{
Mat img1 = _img1.getMat();
Mat gradx, grady, imgDiff;
Mat img2;
......@@ -66,11 +67,11 @@ void MapperGradSimilar::calculate(
CV_DbgAssert(img1.channels() == image2.channels());
CV_DbgAssert(img1.channels() == 1 || img1.channels() == 3);
if(!res.empty()) {
if(!init.empty()) {
// We have initial values for the registration: we move img2 to that initial reference
res->inverseWarp(image2, img2);
init->inverseWarp(image2, img2);
} else {
img2 = image2;
img2 = image2.getMat();
}
// Get gradient in all channels
......@@ -126,16 +127,19 @@ void MapperGradSimilar::calculate(
Matx<double, 2, 2> linTr(k(0) + 1., k(1), -k(1), k(0) + 1.);
Vec<double, 2> shift(k(2), k(3));
if(res.empty()) {
res = Ptr<Map>(new MapAffine(linTr, shift));
if(init.empty()) {
return Ptr<Map>(new MapAffine(linTr, shift));
} else {
MapAffine newTr(linTr, shift);
res->compose(newTr);
Ptr<MapAffine> newTr(new MapAffine(linTr, shift));
MapAffine* initPtr = dynamic_cast<MapAffine*>(init.get());
Ptr<MapAffine> oldTr(new MapAffine(initPtr->getLinTr(), initPtr->getShift()));
oldTr->compose(newTr);
return oldTr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
cv::Ptr<Map> MapperGradSimilar::getMap(void) const
cv::Ptr<Map> MapperGradSimilar::getMap() const
{
return cv::Ptr<Map>(new MapAffine());
}
......
......@@ -48,22 +48,23 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapperPyramid::MapperPyramid(const Mapper& baseMapper)
: numLev_(3), numIterPerScale_(3), baseMapper_(baseMapper)
MapperPyramid::MapperPyramid(Ptr<Mapper> baseMapper)
: numLev_(3), numIterPerScale_(3), baseMapper_(*baseMapper)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapperPyramid::calculate(const Mat& img1, const Mat& image2, Ptr<Map>& res) const
Ptr<Map> MapperPyramid::calculate(InputArray _img1, InputArray image2, Ptr<Map> init) const
{
Mat img1 = _img1.getMat();
Mat img2;
if(!res.empty()) {
if(!init.empty()) {
// We have initial values for the registration: we move img2 to that initial reference
res->inverseWarp(image2, img2);
init->inverseWarp(image2, img2);
} else {
res = baseMapper_.getMap();
img2 = image2;
init = baseMapper_.getMap();
img2 = image2.getMat();
}
cv::Ptr<Map> ident = baseMapper_.getMap();
......@@ -72,29 +73,30 @@ void MapperPyramid::calculate(const Mat& img1, const Mat& image2, Ptr<Map>& res)
vector<Mat> pyrIm1(numLev_), pyrIm2(numLev_);
pyrIm1[0] = img1;
pyrIm2[0] = img2;
for(size_t im_i = 1; im_i < numLev_; ++im_i) {
for(int im_i = 1; im_i < numLev_; ++im_i) {
pyrDown(pyrIm1[im_i - 1], pyrIm1[im_i]);
pyrDown(pyrIm2[im_i - 1], pyrIm2[im_i]);
}
Mat currRef, currImg;
for(size_t lv_i = 0; lv_i < numLev_; ++lv_i) {
for(int lv_i = 0; lv_i < numLev_; ++lv_i) {
currRef = pyrIm1[numLev_ - 1 - lv_i];
currImg = pyrIm2[numLev_ - 1 - lv_i];
// Scale the transformation as we are incresing the resolution in each iteration
if(lv_i != 0) {
ident->scale(2.);
}
for(size_t it_i = 0; it_i < numIterPerScale_; ++it_i) {
baseMapper_.calculate(currRef, currImg, ident);
for(int it_i = 0; it_i < numIterPerScale_; ++it_i) {
ident = baseMapper_.calculate(currRef, currImg, ident);
}
}
res->compose(*ident.get());
init->compose(ident);
return init;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
cv::Ptr<Map> MapperPyramid::getMap(void) const
cv::Ptr<Map> MapperPyramid::getMap() const
{
return cv::Ptr<Map>();
}
......
......@@ -45,7 +45,7 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapProjec::MapProjec(void)
MapProjec::MapProjec()
: projTr_(Matx<double, 3, 3>::eye())
{
}
......@@ -57,13 +57,14 @@ MapProjec::MapProjec(const Matx<double, 3, 3>& projTr)
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapProjec::~MapProjec(void)
MapProjec::~MapProjec()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapProjec::inverseWarp(const Mat& img1, Mat& img2) const
void MapProjec::inverseWarp(InputArray _img1, OutputArray img2) const
{
Mat img1 = _img1.getMat();
// Rows and columns in destination
Mat dest_r, dest_c;
dest_r.create(img1.size(), CV_32FC1);
......@@ -95,10 +96,10 @@ Ptr<Map> MapProjec::inverseMap(void) const
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapProjec::compose(const Map& map)
void MapProjec::compose(Ptr<Map> map)
{
// Composition of homographies H and H' is (H o H') = H'*H
const MapProjec& mapProj = static_cast<const MapProjec&>(map);
const MapProjec& mapProj = static_cast<const MapProjec&>(*map);
Matx<double, 3, 3> compProjTr = mapProj.getProjTr()*projTr_;
projTr_ = compProjTr;
}
......
......@@ -46,23 +46,26 @@ namespace reg {
////////////////////////////////////////////////////////////////////////////////////////////////////
MapShift::MapShift(void) : shift_()
MapShift::MapShift() : shift_()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapShift::MapShift(const Vec<double, 2>& shift) : shift_(shift)
MapShift::MapShift(InputArray shift)
{
Mat shiftMat = shift.getMat();
shiftMat.copyTo(shift_);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MapShift::~MapShift(void)
MapShift::~MapShift()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapShift::inverseWarp(const Mat& img1, Mat& img2) const
void MapShift::inverseWarp(InputArray _img1, OutputArray img2) const
{
Mat img1 = _img1.getMat();
// Rows and columns in destination
Mat dest_r, dest_c;
dest_r.create(img1.size(), CV_32FC1);
......@@ -91,10 +94,10 @@ Ptr<Map> MapShift::inverseMap(void) const
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void MapShift::compose(const Map& map)
void MapShift::compose(cv::Ptr<Map> map)
{
// Composition of transformations T and T' is (T o T') = b + b'
const MapShift& mapShift = static_cast<const MapShift&>(map);
const MapShift& mapShift = static_cast<const MapShift&>(*map);
shift_ += mapShift.getShift();
}
......
......@@ -59,11 +59,13 @@ using namespace std;
using namespace cv;
using namespace cv::reg;
#define REG_DEBUG_OUTPUT 0
class RegTest : public testing::Test
{
public:
void loadImage();
void loadImage(int dstDataType = CV_32FC3);
void testShift();
void testEuclidean();
......@@ -84,20 +86,20 @@ void RegTest::testShift()
mapTest.warp(img1, img2);
// Register
MapperGradShift mapper;
Ptr<Mapper> mapper = makePtr<MapperGradShift>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapShift* mapShift = dynamic_cast<MapShift*>(mapPtr.get());
Ptr<MapShift> mapShift = MapTypeCaster::toShift(mapPtr);
#if REG_DEBUG_OUTPUT
cout << endl << "--- Testing shift mapper ---" << endl;
cout << Mat(shift) << endl;
cout << Mat(mapShift->getShift()) << endl;
#endif
// Check accuracy
Ptr<Map> mapInv(mapShift->inverseMap());
mapTest.compose(*mapInv.get());
mapTest.compose(mapInv);
double shNorm = norm(mapTest.getShift());
EXPECT_LE(shNorm, 0.1);
}
......@@ -116,22 +118,22 @@ void RegTest::testEuclidean()
mapTest.warp(img1, img2);
// Register
MapperGradEuclid mapper;
Ptr<Mapper> mapper = makePtr<MapperGradEuclid>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
Ptr<MapAffine> mapAff = MapTypeCaster::toAffine(mapPtr);
#if REG_DEBUG_OUTPUT
cout << endl << "--- Testing Euclidean mapper ---" << endl;
cout << Mat(linTr) << endl;
cout << Mat(shift) << endl;
cout << Mat(mapAff->getLinTr()) << endl;
cout << Mat(mapAff->getShift()) << endl;
#endif
// Check accuracy
Ptr<Map> mapInv(mapAff->inverseMap());
mapTest.compose(*mapInv.get());
mapTest.compose(mapInv);
double shNorm = norm(mapTest.getShift());
EXPECT_LE(shNorm, 0.1);
double linTrNorm = norm(mapTest.getLinTr());
......@@ -154,22 +156,23 @@ void RegTest::testSimilarity()
mapTest.warp(img1, img2);
// Register
MapperGradSimilar mapper;
Ptr<Mapper> mapper = makePtr<MapperGradSimilar>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
Ptr<MapAffine> mapAff = MapTypeCaster::toAffine(mapPtr);
#if REG_DEBUG_OUTPUT
cout << endl << "--- Testing similarity mapper ---" << endl;
cout << Mat(linTr) << endl;
cout << Mat(shift) << endl;
cout << Mat(mapAff->getLinTr()) << endl;
cout << Mat(mapAff->getShift()) << endl;
#endif
// Check accuracy
Ptr<Map> mapInv(mapAff->inverseMap());
mapTest.compose(*mapInv.get());
mapTest.compose(mapInv);
double shNorm = norm(mapTest.getShift());
EXPECT_LE(shNorm, 0.1);
double linTrNorm = norm(mapTest.getLinTr());
......@@ -188,22 +191,23 @@ void RegTest::testAffine()
mapTest.warp(img1, img2);
// Register
MapperGradAffine mapper;
Ptr<Mapper> mapper = makePtr<MapperGradAffine>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapAffine* mapAff = dynamic_cast<MapAffine*>(mapPtr.get());
Ptr<MapAffine> mapAff = MapTypeCaster::toAffine(mapPtr);
#if REG_DEBUG_OUTPUT
cout << endl << "--- Testing affine mapper ---" << endl;
cout << Mat(linTr) << endl;
cout << Mat(shift) << endl;
cout << Mat(mapAff->getLinTr()) << endl;
cout << Mat(mapAff->getShift()) << endl;
#endif
// Check accuracy
Ptr<Map> mapInv(mapAff->inverseMap());
mapTest.compose(*mapInv.get());
mapTest.compose(mapInv);
double shNorm = norm(mapTest.getShift());
EXPECT_LE(shNorm, 0.1);
double linTrNorm = norm(mapTest.getLinTr());
......@@ -222,34 +226,34 @@ void RegTest::testProjective()
mapTest.warp(img1, img2);
// Register
MapperGradProj mapper;
Ptr<Mapper> mapper = makePtr<MapperGradProj>();
MapperPyramid mappPyr(mapper);
Ptr<Map> mapPtr;
mappPyr.calculate(img1, img2, mapPtr);
Ptr<Map> mapPtr = mappPyr.calculate(img1, img2);
// Print result
MapProjec* mapProj = dynamic_cast<MapProjec*>(mapPtr.get());
Ptr<MapProjec> mapProj = MapTypeCaster::toProjec(mapPtr);
mapProj->normalize();
#if REG_DEBUG_OUTPUT
cout << endl << "--- Testing projective transformation mapper ---" << endl;
cout << Mat(projTr) << endl;
cout << Mat(mapProj->getProjTr()) << endl;
#endif
// Check accuracy
Ptr<Map> mapInv(mapProj->inverseMap());
mapTest.compose(*mapInv.get());
mapTest.compose(mapInv);
double projNorm = norm(mapTest.getProjTr());
EXPECT_LE(projNorm, sqrt(3.) + 0.01);
EXPECT_GE(projNorm, sqrt(3.) - 0.01);
}
void RegTest::loadImage()
void RegTest::loadImage(int dstDataType)
{
const string imageName = cvtest::TS::ptr()->get_data_path() + "reg/home.png";
img1 = imread(imageName, -1);
ASSERT_TRUE(img1.data != 0);
// Convert to double, 3 channels
img1.convertTo(img1, CV_64FC3);
ASSERT_TRUE(!img1.empty());
img1.convertTo(img1, dstDataType);
}
......@@ -282,3 +286,15 @@ TEST_F(RegTest, projective)
loadImage();
testProjective();
}
TEST_F(RegTest, projective_dt64fc3)
{
loadImage(CV_64FC3);
testProjective();
}
TEST_F(RegTest, projective_dt64fc1)
{
loadImage(CV_64FC1);
testProjective();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment