diff --git a/modules/gapi/include/opencv2/gapi/imgproc.hpp b/modules/gapi/include/opencv2/gapi/imgproc.hpp index 0e4254cb87..e41c2507f2 100644 --- a/modules/gapi/include/opencv2/gapi/imgproc.hpp +++ b/modules/gapi/include/opencv2/gapi/imgproc.hpp @@ -46,7 +46,7 @@ void validateFindingContoursMeta(const int depth, const int chan, const int mode // Checks if the passed mat is a set of n-dimentional points of the given depth bool isPointsVector(const int chan, const cv::Size &size, const int depth, - const int n, const int ddepth) + const int n, const int ddepth = -1) { return (ddepth == depth || ddepth < 0) && ((chan == n && (size.height == 1 || size.width == 1)) || @@ -234,6 +234,70 @@ namespace imgproc { } }; + G_TYPED_KERNEL(GFitLine2DMat, (GMat,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DMat") { + static GOpaqueDesc outMeta(GMatDesc in,DistanceTypes,double,double,double) { + GAPI_Assert(isPointsVector(in.chan, in.size, in.depth, 2, -1)); + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DVector32S, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DVector32S") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DVector32F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DVector32F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine2DVector64F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine2DVector64F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DMat, (GMat,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DMat") { + static GOpaqueDesc outMeta(GMatDesc in,int,double,double,double) { + GAPI_Assert(isPointsVector(in.chan, in.size, in.depth, 3, -1)); + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DVector32S, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DVector32S") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DVector32F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DVector32F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + + G_TYPED_KERNEL(GFitLine3DVector64F, + (GArray,DistanceTypes,double,double,double)>, + "org.opencv.imgproc.shape.fitLine3DVector64F") { + static GOpaqueDesc outMeta(GArrayDesc,DistanceTypes,double,double,double) { + return empty_gopaque_desc(); + } + }; + G_TYPED_KERNEL(GBGR2RGB, , "org.opencv.imgproc.colorconvert.bgr2rgb") { static GMatDesc outMeta(GMatDesc in) { return in; // type still remains CV_8UC3; @@ -1111,6 +1175,153 @@ Calculates the up-right bounding rectangle of a point set. */ GAPI_EXPORTS GOpaque boundingRect(const GArray& src); +/** @brief Fits a line to a 2D point set. + +The function fits a line to a 2D point set by minimizing \f$\sum_i \rho(r_i)\f$ where +\f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance +function, one of the following: +- DIST_L2 +\f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f] +- DIST_L1 +\f[\rho (r) = r\f] +- DIST_L12 +\f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f] +- DIST_FAIR +\f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f] +- DIST_WELSCH +\f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f] +- DIST_HUBER +\f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] + +The algorithm is based on the M-estimator ( ) technique +that iteratively fits the line using the weighted least-squares algorithm. After each iteration the +weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DMat" + +@param src Input set of 2D points stored in one of possible containers: Mat, +std::vector, std::vector, std::vector. + +@note In case of an N-dimentional points' set given, Mat should be 2-dimensional, have a single row +or column if there are N channels, or have N columns if there is a single channel. + +@param distType Distance used by the M-estimator, see #DistanceTypes. @ref DIST_USER +and @ref DIST_C are not suppored. +@param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value +is chosen. +@param reps Sufficient accuracy for the radius (distance between the coordinate origin and the +line). 1.0 would be a good default value for reps. If it is 0, a default value is chosen. +@param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for aeps. +If it is 0, a default value is chosen. + +@return Output line parameters: a vector of 4 elements (like Vec4f) - (vx, vy, x0, y0), +where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line. + */ +GAPI_EXPORTS GOpaque fitLine2D(const GMat& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DVector32S" + + */ +GAPI_EXPORTS GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DVector32F" + + */ +GAPI_EXPORTS GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine2DVector64F" + + */ +GAPI_EXPORTS GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @brief Fits a line to a 3D point set. + +The function fits a line to a 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where +\f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance +function, one of the following: +- DIST_L2 +\f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f] +- DIST_L1 +\f[\rho (r) = r\f] +- DIST_L12 +\f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f] +- DIST_FAIR +\f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f] +- DIST_WELSCH +\f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f] +- DIST_HUBER +\f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] + +The algorithm is based on the M-estimator ( ) technique +that iteratively fits the line using the weighted least-squares algorithm. After each iteration the +weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DMat" + +@param src Input set of 3D points stored in one of possible containers: Mat, +std::vector, std::vector, std::vector. + +@note In case of an N-dimentional points' set given, Mat should be 2-dimensional, have a single row +or column if there are N channels, or have N columns if there is a single channel. + +@param distType Distance used by the M-estimator, see #DistanceTypes. @ref DIST_USER +and @ref DIST_C are not suppored. +@param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value +is chosen. +@param reps Sufficient accuracy for the radius (distance between the coordinate origin and the +line). 1.0 would be a good default value for reps. If it is 0, a default value is chosen. +@param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for aeps. +If it is 0, a default value is chosen. + +@return Output line parameters: a vector of 6 elements (like Vec6f) - (vx, vy, vz, x0, y0, z0), +where (vx, vy, vz) is a normalized vector collinear to the line and (x0, y0, z0) is a point on +the line. + */ +GAPI_EXPORTS GOpaque fitLine3D(const GMat& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DVector32S" + + */ +GAPI_EXPORTS GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DVector32F" + + */ +GAPI_EXPORTS GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + +/** @overload + +@note Function textual ID is "org.opencv.imgproc.shape.fitLine3DVector64F" + + */ +GAPI_EXPORTS GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param = 0., const double reps = 0., + const double aeps = 0.); + //! @} gapi_shape //! @addtogroup gapi_colorconvert diff --git a/modules/gapi/src/api/kernels_imgproc.cpp b/modules/gapi/src/api/kernels_imgproc.cpp index faf8de54c7..41085a7ebf 100644 --- a/modules/gapi/src/api/kernels_imgproc.cpp +++ b/modules/gapi/src/api/kernels_imgproc.cpp @@ -164,6 +164,54 @@ GOpaque boundingRect(const GArray& src) return imgproc::GBoundingRectVector32F::on(src); } +GOpaque fitLine2D(const GMat& src, const DistanceTypes distType, const double param, + const double reps, const double aeps) +{ + return imgproc::GFitLine2DMat::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param, const double reps, const double aeps) +{ + return imgproc::GFitLine2DVector32S::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param, const double reps, const double aeps) +{ + return imgproc::GFitLine2DVector32F::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine2D(const GArray& src, const DistanceTypes distType, + const double param, const double reps, const double aeps) +{ + return imgproc::GFitLine2DVector64F::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine3D(const GMat& src, const DistanceTypes distType, const double param, + const double reps, const double aeps) +{ + return imgproc::GFitLine3DMat::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param, const double reps, const double aeps) +{ + return imgproc::GFitLine3DVector32S::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param, const double reps, const double aeps) +{ + return imgproc::GFitLine3DVector32F::on(src, distType, param, reps, aeps); +} + +GOpaque fitLine3D(const GArray& src, const DistanceTypes distType, + const double param, const double reps, const double aeps) +{ + return imgproc::GFitLine3DVector64F::on(src, distType, param, reps, aeps); +} + GMat BGR2RGB(const GMat& src) { return imgproc::GBGR2RGB::on(src); diff --git a/modules/gapi/src/backends/cpu/gcpuimgproc.cpp b/modules/gapi/src/backends/cpu/gcpuimgproc.cpp index 9eca0f12f0..6cbf0d32f0 100644 --- a/modules/gapi/src/backends/cpu/gcpuimgproc.cpp +++ b/modules/gapi/src/backends/cpu/gcpuimgproc.cpp @@ -285,6 +285,78 @@ GAPI_OCV_KERNEL(GCPUBoundingRectVector32F, cv::gapi::imgproc::GBoundingRectVecto } }; +GAPI_OCV_KERNEL(GCPUFitLine2DMat, cv::gapi::imgproc::GFitLine2DMat) +{ + static void run(const cv::Mat& in, const cv::DistanceTypes distType, const double param, + const double reps, const double aeps, cv::Vec4f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine2DVector32S, cv::gapi::imgproc::GFitLine2DVector32S) +{ + static void run(const std::vector& in, const cv::DistanceTypes distType, + const double param, const double reps, const double aeps, cv::Vec4f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine2DVector32F, cv::gapi::imgproc::GFitLine2DVector32F) +{ + static void run(const std::vector& in, const cv::DistanceTypes distType, + const double param, const double reps, const double aeps, cv::Vec4f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine2DVector64F, cv::gapi::imgproc::GFitLine2DVector64F) +{ + static void run(const std::vector& in, const cv::DistanceTypes distType, + const double param, const double reps, const double aeps, cv::Vec4f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine3DMat, cv::gapi::imgproc::GFitLine3DMat) +{ + static void run(const cv::Mat& in, const cv::DistanceTypes distType, const double param, + const double reps, const double aeps, cv::Vec6f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine3DVector32S, cv::gapi::imgproc::GFitLine3DVector32S) +{ + static void run(const std::vector& in, const cv::DistanceTypes distType, + const double param, const double reps, const double aeps, cv::Vec6f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine3DVector32F, cv::gapi::imgproc::GFitLine3DVector32F) +{ + static void run(const std::vector& in, const cv::DistanceTypes distType, + const double param, const double reps, const double aeps, cv::Vec6f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + +GAPI_OCV_KERNEL(GCPUFitLine3DVector64F, cv::gapi::imgproc::GFitLine3DVector64F) +{ + static void run(const std::vector& in, const cv::DistanceTypes distType, + const double param, const double reps, const double aeps, cv::Vec6f& out) + { + cv::fitLine(in, out, distType, param, reps, aeps); + } +}; + GAPI_OCV_KERNEL(GCPUBGR2RGB, cv::gapi::imgproc::GBGR2RGB) { static void run(const cv::Mat& in, cv::Mat &out) @@ -569,6 +641,14 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels() , GCPUBoundingRectMat , GCPUBoundingRectVector32S , GCPUBoundingRectVector32F + , GCPUFitLine2DMat + , GCPUFitLine2DVector32S + , GCPUFitLine2DVector32F + , GCPUFitLine2DVector64F + , GCPUFitLine3DMat + , GCPUFitLine3DVector32S + , GCPUFitLine3DVector32F + , GCPUFitLine3DVector64F , GCPUYUV2RGB , GCPUBGR2I420 , GCPURGB2I420 diff --git a/modules/gapi/test/common/gapi_imgproc_tests.hpp b/modules/gapi/test/common/gapi_imgproc_tests.hpp index b27da28c87..b48b7b6732 100644 --- a/modules/gapi/test/common/gapi_imgproc_tests.hpp +++ b/modules/gapi/test/common/gapi_imgproc_tests.hpp @@ -83,6 +83,22 @@ GAPI_TEST_FIXTURE(BoundingRectVector32STest, initNothing, FIXTURE_API(CompareRec GAPI_TEST_FIXTURE(BoundingRectVector32FTest, initNothing, FIXTURE_API(CompareRects), 1, cmpF) GAPI_TEST_FIXTURE(BGR2RGBTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) GAPI_TEST_FIXTURE(RGB2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) +GAPI_TEST_FIXTURE(FitLine2DMatVectorTest, initMatByPointsVectorRandU, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine2DVector32STest, initNothing, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine2DVector32FTest, initNothing, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine2DVector64FTest, initNothing, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine3DMatVectorTest, initMatByPointsVectorRandU, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine3DVector32STest, initNothing, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine3DVector32FTest, initNothing, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) +GAPI_TEST_FIXTURE(FitLine3DVector64FTest, initNothing, + FIXTURE_API(CompareVecs,cv::DistanceTypes), 2, cmpF, distType) GAPI_TEST_FIXTURE(BGR2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) GAPI_TEST_FIXTURE(RGB2YUVTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) GAPI_TEST_FIXTURE(BGR2I420Test, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) diff --git a/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp b/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp index 91e676c5e7..2a4f2e64ea 100644 --- a/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp +++ b/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp @@ -752,6 +752,192 @@ TEST_P(BoundingRectVector32FTest, AccuracyTest) } } +TEST_P(FitLine2DMatVectorTest, AccuracyTest) +{ + cv::Vec4f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + // G-API code ////////////////////////////////////////////////////////////// + cv::GMat in; + auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_mat1), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_mat1, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine2DVector32STest, AccuracyTest) +{ + cv::Vec4f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + std::vector in_vec; + initPointsVectorRandU(sz.width, in_vec); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GArray in; + auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine2DVector32FTest, AccuracyTest) +{ + cv::Vec4f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + std::vector in_vec; + initPointsVectorRandU(sz.width, in_vec); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GArray in; + auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine2DVector64FTest, AccuracyTest) +{ + cv::Vec4f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + std::vector in_vec; + initPointsVectorRandU(sz.width, in_vec); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GArray in; + auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine3DMatVectorTest, AccuracyTest) +{ + cv::Vec6f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + // G-API code ////////////////////////////////////////////////////////////// + cv::GMat in; + auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_mat1), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_mat1, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine3DVector32STest, AccuracyTest) +{ + cv::Vec6f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + std::vector in_vec; + initPointsVectorRandU(sz.width, in_vec); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GArray in; + auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine3DVector32FTest, AccuracyTest) +{ + cv::Vec6f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + std::vector in_vec; + initPointsVectorRandU(sz.width, in_vec); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GArray in; + auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + +TEST_P(FitLine3DVector64FTest, AccuracyTest) +{ + cv::Vec6f out_vec_gapi, out_vec_ocv; + double paramDefault = 0., repsDefault = 0., aepsDefault = 0.; + + std::vector in_vec; + initPointsVectorRandU(sz.width, in_vec); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GArray in; + auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs()); + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv)); + } +} + TEST_P(BGR2RGBTest, AccuracyTest) { // G-API code ////////////////////////////////////////////////////////////// diff --git a/modules/gapi/test/common/gapi_tests_common.hpp b/modules/gapi/test/common/gapi_tests_common.hpp index 948476fa10..514fa2be38 100644 --- a/modules/gapi/test/common/gapi_tests_common.hpp +++ b/modules/gapi/test/common/gapi_tests_common.hpp @@ -74,6 +74,50 @@ namespace } #endif // WINRT } + + template inline void initPointRandU(cv::RNG &rng, cv::Point_& pt) + { + GAPI_Assert(std::is_integral::value); + pt = cv::Point_(static_cast(static_cast(rng(CHAR_MAX + 1U))), + static_cast(static_cast(rng(CHAR_MAX + 1U)))); + } + + template inline void initPointRandU(cv::RNG &rng, cv::Point3_& pt) + { + GAPI_Assert(std::is_integral::value); + pt = cv::Point3_(static_cast(static_cast(rng(CHAR_MAX + 1U))), + static_cast(static_cast(rng(CHAR_MAX + 1U))), + static_cast(static_cast(rng(CHAR_MAX + 1U)))); + } + + template inline void initFloatPointRandU(cv::RNG &rng, cv::Point_ &pt) + { + GAPI_Assert(std::is_floating_point::value); + static const int fscale = 256; // avoid bits near ULP, generate stable test input + pt = cv::Point_(rng.uniform(0, 255 * fscale) / static_cast(fscale), + rng.uniform(0, 255 * fscale) / static_cast(fscale)); + } + + template<> inline void initPointRandU(cv::RNG &rng, cv::Point2f &pt) + { initFloatPointRandU(rng, pt); } + + template<> inline void initPointRandU(cv::RNG &rng, cv::Point2d &pt) + { initFloatPointRandU(rng, pt); } + + template inline void initFloatPointRandU(cv::RNG &rng, cv::Point3_ &pt) + { + GAPI_Assert(std::is_floating_point::value); + static const int fscale = 256; // avoid bits near ULP, generate stable test input + pt = cv::Point3_(rng.uniform(0, 255 * fscale) / static_cast(fscale), + rng.uniform(0, 255 * fscale) / static_cast(fscale), + rng.uniform(0, 255 * fscale) / static_cast(fscale)); + } + + template<> inline void initPointRandU(cv::RNG &rng, cv::Point3f &pt) + { initFloatPointRandU(rng, pt); } + + template<> inline void initPointRandU(cv::RNG &rng, cv::Point3d &pt) + { initFloatPointRandU(rng, pt); } } // namespace namespace opencv_test @@ -279,6 +323,80 @@ public: } } + template + inline void initPointRandU(cv::RNG& rng, T& pt) + { ::initPointRandU(rng, pt); } + +// Disable unreachable code warning for MSVS 2015 +#if defined _MSC_VER && _MSC_VER < 1910 /*MSVS 2017*/ +#pragma warning(push) +#pragma warning(disable: 4702) +#endif + // initialize std::vector>/std::vector> + template class Pt> + void initPointsVectorRandU(const int sz_in, std::vector> &vec_) + { + cv::RNG& rng = theRNG(); + + vec_.clear(); + vec_.reserve(sz_in); + + for (int i = 0; i < sz_in; i++) + { + Pt pt; + initPointRandU(rng, pt); + vec_.emplace_back(pt); + } + } +#if defined _MSC_VER && _MSC_VER < 1910 /*MSVS 2017*/ +#pragma warning(pop) +#endif + + template + inline void initMatByPointsVectorRandU(const cv::Size &sz_in) + { + std::vector in_vector; + initPointsVectorRandU(sz_in.width, in_vector); + in_mat1 = cv::Mat(in_vector, true); + } + + // initialize Mat by a vector of Points + template