Merge pull request #18790 from OrestChura:oc/fitLine

[G-API]: fitLine() Standard Kernel Implementation

* fitLine API (Mat, 32S, 32F) (2D, 3D)

* Complete fitLine kernel & accuracy tests
 - initialization for vectors of cv::Point and Mats via vectors added
 - comparison functions for Vec<T, n> added:
   - straight average difference comparison
   - comparison by equasion for 2d line
 - stream overload for cv::DistanceTypes added

* Fix precommit warnings

* Fix docs

* Address comments
Try to fix warning

* Disable warning in tests
pull/18842/head
Orest Chura 4 years ago committed by GitHub
parent b866d0dc38
commit 2c6a2f0381
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 213
      modules/gapi/include/opencv2/gapi/imgproc.hpp
  2. 48
      modules/gapi/src/api/kernels_imgproc.cpp
  3. 80
      modules/gapi/src/backends/cpu/gcpuimgproc.cpp
  4. 16
      modules/gapi/test/common/gapi_imgproc_tests.hpp
  5. 186
      modules/gapi/test/common/gapi_imgproc_tests_inl.hpp
  6. 205
      modules/gapi/test/common/gapi_tests_common.hpp
  7. 68
      modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp

@ -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, <GOpaque<Vec4f>(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,
<GOpaque<Vec4f>(GArray<Point2i>,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,
<GOpaque<Vec4f>(GArray<Point2f>,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,
<GOpaque<Vec4f>(GArray<Point2d>,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, <GOpaque<Vec6f>(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,
<GOpaque<Vec6f>(GArray<Point3i>,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,
<GOpaque<Vec6f>(GArray<Point3f>,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,
<GOpaque<Vec6f>(GArray<Point3d>,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, <GMat(GMat)>, "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<Rect> boundingRect(const GArray<Point2f>& 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 ( <http://en.wikipedia.org/wiki/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<cv::Point2i>, std::vector<cv::Point2f>, std::vector<cv::Point2d>.
@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<Vec4f> 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<Vec4f> fitLine2D(const GArray<Point2i>& 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<Vec4f> fitLine2D(const GArray<Point2f>& 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<Vec4f> fitLine2D(const GArray<Point2d>& 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 ( <http://en.wikipedia.org/wiki/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<cv::Point3i>, std::vector<cv::Point3f>, std::vector<cv::Point3d>.
@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<Vec6f> 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<Vec6f> fitLine3D(const GArray<Point3i>& 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<Vec6f> fitLine3D(const GArray<Point3f>& 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<Vec6f> fitLine3D(const GArray<Point3d>& src, const DistanceTypes distType,
const double param = 0., const double reps = 0.,
const double aeps = 0.);
//! @} gapi_shape
//! @addtogroup gapi_colorconvert

@ -164,6 +164,54 @@ GOpaque<Rect> boundingRect(const GArray<Point2f>& src)
return imgproc::GBoundingRectVector32F::on(src);
}
GOpaque<Vec4f> 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<Vec4f> fitLine2D(const GArray<Point2i>& src, const DistanceTypes distType,
const double param, const double reps, const double aeps)
{
return imgproc::GFitLine2DVector32S::on(src, distType, param, reps, aeps);
}
GOpaque<Vec4f> fitLine2D(const GArray<Point2f>& src, const DistanceTypes distType,
const double param, const double reps, const double aeps)
{
return imgproc::GFitLine2DVector32F::on(src, distType, param, reps, aeps);
}
GOpaque<Vec4f> fitLine2D(const GArray<Point2d>& src, const DistanceTypes distType,
const double param, const double reps, const double aeps)
{
return imgproc::GFitLine2DVector64F::on(src, distType, param, reps, aeps);
}
GOpaque<Vec6f> 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<Vec6f> fitLine3D(const GArray<Point3i>& src, const DistanceTypes distType,
const double param, const double reps, const double aeps)
{
return imgproc::GFitLine3DVector32S::on(src, distType, param, reps, aeps);
}
GOpaque<Vec6f> fitLine3D(const GArray<Point3f>& src, const DistanceTypes distType,
const double param, const double reps, const double aeps)
{
return imgproc::GFitLine3DVector32F::on(src, distType, param, reps, aeps);
}
GOpaque<Vec6f> fitLine3D(const GArray<Point3d>& 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);

@ -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<cv::Point2i>& 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<cv::Point2f>& 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<cv::Point2d>& 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<cv::Point3i>& 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<cv::Point3f>& 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<cv::Point3d>& 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

@ -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<cv::Point_>,
FIXTURE_API(CompareVecs<float, 4>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine2DVector32STest, initNothing,
FIXTURE_API(CompareVecs<float, 4>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine2DVector32FTest, initNothing,
FIXTURE_API(CompareVecs<float, 4>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine2DVector64FTest, initNothing,
FIXTURE_API(CompareVecs<float, 4>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine3DMatVectorTest, initMatByPointsVectorRandU<cv::Point3_>,
FIXTURE_API(CompareVecs<float, 6>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine3DVector32STest, initNothing,
FIXTURE_API(CompareVecs<float, 6>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine3DVector32FTest, initNothing,
FIXTURE_API(CompareVecs<float, 6>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine3DVector64FTest, initNothing,
FIXTURE_API(CompareVecs<float, 6>,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)

@ -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<cv::Point2i> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2i> 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<cv::Point2f> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2f> 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<cv::Point2d> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2d> 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<cv::Point3i> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point3i> 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<cv::Point3f> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point3f> 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<cv::Point3d> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point3d> 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 //////////////////////////////////////////////////////////////

@ -74,6 +74,50 @@ namespace
}
#endif // WINRT
}
template <typename T> inline void initPointRandU(cv::RNG &rng, cv::Point_<T>& pt)
{
GAPI_Assert(std::is_integral<T>::value);
pt = cv::Point_<T>(static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))),
static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))));
}
template <typename T> inline void initPointRandU(cv::RNG &rng, cv::Point3_<T>& pt)
{
GAPI_Assert(std::is_integral<T>::value);
pt = cv::Point3_<T>(static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))),
static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))),
static_cast<T>(static_cast<char>(rng(CHAR_MAX + 1U))));
}
template <typename F> inline void initFloatPointRandU(cv::RNG &rng, cv::Point_<F> &pt)
{
GAPI_Assert(std::is_floating_point<F>::value);
static const int fscale = 256; // avoid bits near ULP, generate stable test input
pt = cv::Point_<F>(rng.uniform(0, 255 * fscale) / static_cast<F>(fscale),
rng.uniform(0, 255 * fscale) / static_cast<F>(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 <typename F> inline void initFloatPointRandU(cv::RNG &rng, cv::Point3_<F> &pt)
{
GAPI_Assert(std::is_floating_point<F>::value);
static const int fscale = 256; // avoid bits near ULP, generate stable test input
pt = cv::Point3_<F>(rng.uniform(0, 255 * fscale) / static_cast<F>(fscale),
rng.uniform(0, 255 * fscale) / static_cast<F>(fscale),
rng.uniform(0, 255 * fscale) / static_cast<F>(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 <typename T>
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<cv::Point_<T>>/std::vector<cv::Point3_<T>>
template <typename T, template <typename> class Pt>
void initPointsVectorRandU(const int sz_in, std::vector<Pt<T>> &vec_)
{
cv::RNG& rng = theRNG();
vec_.clear();
vec_.reserve(sz_in);
for (int i = 0; i < sz_in; i++)
{
Pt<T> pt;
initPointRandU(rng, pt);
vec_.emplace_back(pt);
}
}
#if defined _MSC_VER && _MSC_VER < 1910 /*MSVS 2017*/
#pragma warning(pop)
#endif
template<typename Pt>
inline void initMatByPointsVectorRandU(const cv::Size &sz_in)
{
std::vector<Pt> in_vector;
initPointsVectorRandU(sz_in.width, in_vector);
in_mat1 = cv::Mat(in_vector, true);
}
// initialize Mat by a vector of Points
template<template <typename> class Pt>
inline void initMatByPointsVectorRandU(int type, cv::Size sz_in, int)
{
int depth = CV_MAT_DEPTH(type);
switch (depth)
{
case CV_8U:
initMatByPointsVectorRandU<Pt<uchar>>(sz_in);
break;
case CV_8S:
initMatByPointsVectorRandU<Pt<char>>(sz_in);
break;
case CV_16U:
initMatByPointsVectorRandU<Pt<ushort>>(sz_in);
break;
case CV_16S:
initMatByPointsVectorRandU<Pt<short>>(sz_in);
break;
case CV_32S:
initMatByPointsVectorRandU<Pt<int>>(sz_in);
break;
case CV_32F:
initMatByPointsVectorRandU<Pt<float>>(sz_in);
break;
case CV_64F:
initMatByPointsVectorRandU<Pt<double>>(sz_in);
break;
case CV_16F:
initMatByPointsVectorRandU<Pt<cv::float16_t>>(sz_in);
break;
default:
GAPI_Assert(false && "Unsupported depth");
break;
}
}
// empty function intended to show that nothing is to be initialized via TestFunctional methods
void initNothing(int, cv::Size, int, bool = true) {}
};
@ -469,6 +587,9 @@ template<typename Elem>
using compare_vector_f = std::function<bool(const std::vector<Elem> &a,
const std::vector<Elem> &b)>;
template<typename Elem, int cn>
using compare_vec_f = std::function<bool(const cv::Vec<Elem, cn> &a, const cv::Vec<Elem, cn> &b)>;
template<typename T1, typename T2>
struct CompareF
{
@ -495,6 +616,9 @@ using CompareRects = CompareF<cv::Rect, cv::Rect>;
template<typename Elem>
using CompareVectors = CompareF<std::vector<Elem>, std::vector<Elem>>;
template<typename Elem, int cn>
using CompareVecs = CompareF<cv::Vec<Elem, cn>, cv::Vec<Elem, cn>>;
template<typename T>
struct Wrappable
{
@ -580,6 +704,27 @@ struct WrappableVector
}
};
template<typename T, typename Elem, int cn>
struct WrappableVec
{
compare_vec_f<Elem, cn> to_compare_f()
{
T t = *static_cast<T* const>(this);
return [t](const cv::Vec<Elem, cn> &a, const cv::Vec<Elem, cn> &b)
{
return t(a, b);
};
}
CompareVecs<Elem, cn> to_compare_obj()
{
T t = *static_cast<T* const>(this);
std::stringstream ss;
ss << t;
return CompareVecs<Elem, cn>(to_compare_f(), ss.str());
}
};
class AbsExact : public Wrappable<AbsExact>
{
@ -855,6 +1000,41 @@ public:
return os << "AbsExactVector()";
}
};
template<typename Elem, int cn>
class RelDiffToleranceVec : public WrappableVec<RelDiffToleranceVec<Elem, cn>, Elem, cn>
{
public:
RelDiffToleranceVec(double tol) : _tol(tol) {}
bool operator() (const cv::Vec<Elem, cn> &in1, const cv::Vec<Elem, cn> &in2) const
{
double abs_err = cv::norm(in1, in2, cv::NORM_L1);
double in2_norm = cv::norm(in2, cv::NORM_L1);
// Checks to avoid dividing by zero
double err = abs_err ? abs_err / (in2_norm ? in2_norm : cv::norm(in1, cv::NORM_L1))
: abs_err;
if (err > _tol)
{
std::cout << "RelDiffToleranceVec error: err=" << err << " tolerance=" << _tol;
for (int i = 0; i < cn; i++)
{
std::cout << " in1[" << i << "]=" << in1[i] << " in2[" << i << "]=" << in2[i];
}
std::cout << std::endl;
return false;
}
else
{
return true;
}
}
friend std::ostream& operator<<(std::ostream& os, const RelDiffToleranceVec<Elem, cn>& obj)
{
return os << "RelDiffToleranceVec(" << std::to_string(obj._tol) << ")";
}
private:
double _tol;
};
} // namespace opencv_test
namespace
@ -879,6 +1059,12 @@ inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_vec
{
return os << "compare_vector_f";
}
template<typename Elem, int cn>
inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_vec_f<Elem, cn>&)
{
return os << "compare_vec_f";
}
} // anonymous namespace
// Note: namespace must match the namespace of the type of the printed object
@ -969,6 +1155,25 @@ inline std::ostream& operator<<(std::ostream& os, MorphTypes op)
#undef CASE
return os;
}
inline std::ostream& operator<<(std::ostream& os, DistanceTypes op)
{
#define CASE(v) case DistanceTypes::v: os << #v; break
switch (op)
{
CASE(DIST_USER);
CASE(DIST_L1);
CASE(DIST_L2);
CASE(DIST_C);
CASE(DIST_L12);
CASE(DIST_FAIR);
CASE(DIST_WELSCH);
CASE(DIST_HUBER);
default: GAPI_Assert(false && "unknown DistanceTypes value");
}
#undef CASE
return os;
}
} // namespace cv
#endif //OPENCV_GAPI_TESTS_COMMON_HPP

@ -337,6 +337,74 @@ INSTANTIATE_TEST_CASE_P(BoundingRectVector32STestCPU, BoundingRectVector32STest,
Values(IMGPROC_CPU),
Values(IoUToleranceRect(1e-5).to_compare_obj())));
INSTANTIATE_TEST_CASE_P(FitLine2DMatVectorTestCPU, FitLine2DMatVectorTest,
Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S,
CV_32S, CV_32F, CV_64F),
Values(cv::Size(8, 0), cv::Size(1024, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 4>(0.01).to_compare_obj()),
Values(DIST_L1, DIST_L2, DIST_L12, DIST_FAIR,
DIST_WELSCH, DIST_HUBER)));
INSTANTIATE_TEST_CASE_P(FitLine2DVector32STestCPU, FitLine2DVector32STest,
Combine(Values(-1),
Values(cv::Size(8, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 4>(0.01).to_compare_obj()),
Values(DIST_L1)));
INSTANTIATE_TEST_CASE_P(FitLine2DVector32FTestCPU, FitLine2DVector32FTest,
Combine(Values(-1),
Values(cv::Size(8, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 4>(0.01).to_compare_obj()),
Values(DIST_L1)));
INSTANTIATE_TEST_CASE_P(FitLine2DVector64FTestCPU, FitLine2DVector64FTest,
Combine(Values(-1),
Values(cv::Size(8, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 4>(0.01).to_compare_obj()),
Values(DIST_L1)));
INSTANTIATE_TEST_CASE_P(FitLine3DMatVectorTestCPU, FitLine3DMatVectorTest,
Combine(Values(CV_8UC1, CV_8SC1, CV_16UC1, CV_16SC1,
CV_32SC1, CV_32FC1, CV_64FC1),
Values(cv::Size(8, 0), cv::Size(1024, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 6>(0.01).to_compare_obj()),
Values(DIST_L1, DIST_L2, DIST_L12, DIST_FAIR,
DIST_WELSCH, DIST_HUBER)));
INSTANTIATE_TEST_CASE_P(FitLine3DVector32STestCPU, FitLine3DVector32STest,
Combine(Values(-1),
Values(cv::Size(8, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 6>(0.01).to_compare_obj()),
Values(DIST_L1)));
INSTANTIATE_TEST_CASE_P(FitLine3DVector32FTestCPU, FitLine3DVector32FTest,
Combine(Values(-1),
Values(cv::Size(8, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 6>(0.01).to_compare_obj()),
Values(DIST_L1)));
INSTANTIATE_TEST_CASE_P(FitLine3DVector64FTestCPU, FitLine3DVector64FTest,
Combine(Values(-1),
Values(cv::Size(8, 0)),
Values(-1),
Values(IMGPROC_CPU),
Values(RelDiffToleranceVec<float, 6>(0.01).to_compare_obj()),
Values(DIST_L1)));
INSTANTIATE_TEST_CASE_P(BGR2RGBTestCPU, BGR2RGBTest,
Combine(Values(CV_8UC3),
Values(cv::Size(1280, 720),

Loading…
Cancel
Save