opencv/modules/gapi/src/api/gmat.cpp
Orest Chura 986ad4ff06
Merge pull request #18857 from OrestChura:oc/kmeans
[G-API]: kmeans() Standard Kernel Implementation

* cv::gapi::kmeans kernel implementation
 - 4 overloads:
    - standard GMat - for any dimensionality
    - GMat without bestLabels initialization
    - GArray<Point2f> - for 2D
    - GArray<Point3f> - for 3D
 - Accuracy tests:
   - for every input - 2 tests
   1) without initializing. In this case, no comparison with cv::kmeans is done as kmeans uses random auto-initialization
   2) with initialization
   - in both cases, only 1 attempt is done as after first attempt kmeans initializes bestLabels randomly

* Addressing comments
 - bestLabels is returned to its original place among parameters
 - checkVector and isPointsVector functions are merged into one, shared between core.hpp & imgproc.hpp by placing it into gmat.hpp (and implementation - to gmat.cpp)
 - typos corrected

* addressing comments
 - unified names in tests
 - const added
 - typos

* Addressing comments
 - fixed the doc note
 - ddepth -> expectedDepth, `< 0 ` -> `== -1`

* Fix unsupported cases of input Mat
 - supported: multiple channels, reversed width
 - added test cases for those
 - added notes in docs
 - refactored checkVector to return dimentionality along with quantity

* Addressing comments
 - makes chackVector smaller and (maybe) clearer

* Addressing comments

* Addressing comments
 - cv::checkVector -> cv::gapi::detail

* Addressing comments
 - Changed checkVector: returns bool, quantity & dimensionality as references

* Addressing comments
 - Polishing checkVector
 - FIXME added

* Addressing discussion
 - checkVector: added overload, separate two different functionalities
 - depth assert - out of the function

* Addressing comments
 - quantity -> amount, dimensionality -> dim
 - Fix typos

* Addressing comments
 - fix docs
 - use 2 variable's definitions instead of one (for all non-trivial variables)
2020-11-30 13:18:43 +00:00

183 lines
4.2 KiB
C++

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018 Intel Corporation
#include "precomp.hpp"
#include <ade/util/iota_range.hpp>
#include <ade/util/algorithm.hpp>
#include <opencv2/gapi/own/mat.hpp> //gapi::own::Mat
#include <opencv2/gapi/gmat.hpp>
#include "api/gorigin.hpp"
// cv::GMat public implementation //////////////////////////////////////////////
cv::GMat::GMat()
: m_priv(new GOrigin(GShape::GMAT, GNode::Param()))
{
}
cv::GMat::GMat(const GNode &n, std::size_t out)
: m_priv(new GOrigin(GShape::GMAT, n, out))
{
}
cv::GOrigin& cv::GMat::priv()
{
return *m_priv;
}
const cv::GOrigin& cv::GMat::priv() const
{
return *m_priv;
}
static std::vector<int> checkVectorImpl(const int width, const int height, const int chan,
const int n)
{
if (width == 1 && (n == -1 || n == chan))
{
return {height, chan};
}
else if (height == 1 && (n == -1 || n == chan))
{
return {width, chan};
}
else if (chan == 1 && (n == -1 || n == width))
{
return {height, width};
}
else // input Mat can't be described as vector of points of given dimensionality
{
return {-1, -1};
}
}
int cv::gapi::detail::checkVector(const cv::GMatDesc& in, const size_t n)
{
GAPI_Assert(n != 0u);
return checkVectorImpl(in.size.width, in.size.height, in.chan, static_cast<int>(n))[0];
}
std::vector<int> cv::gapi::detail::checkVector(const cv::GMatDesc& in)
{
return checkVectorImpl(in.size.width, in.size.height, in.chan, -1);
}
namespace{
template <typename T> cv::GMetaArgs vec_descr_of(const std::vector<T> &vec)
{
cv::GMetaArgs vec_descr;
vec_descr.reserve(vec.size());
for(auto& mat : vec){
vec_descr.emplace_back(descr_of(mat));
}
return vec_descr;
}
}
#if !defined(GAPI_STANDALONE)
cv::GMatDesc cv::descr_of(const cv::Mat &mat)
{
const auto mat_dims = mat.size.dims();
if (mat_dims == 2)
return GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}};
std::vector<int> dims(mat_dims);
for (auto i : ade::util::iota(mat_dims)) {
// Note: cv::MatSize is not iterable
dims[i] = mat.size[i];
}
return GMatDesc{mat.depth(), std::move(dims)};
}
#endif
cv::GMatDesc cv::gapi::own::descr_of(const Mat &mat)
{
return (mat.dims.empty())
? GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}}
: GMatDesc{mat.depth(), mat.dims};
}
#if !defined(GAPI_STANDALONE)
cv::GMatDesc cv::descr_of(const cv::UMat &mat)
{
GAPI_Assert(mat.size.dims() == 2);
return GMatDesc{ mat.depth(), mat.channels(),{ mat.cols, mat.rows } };
}
cv::GMetaArgs cv::descrs_of(const std::vector<cv::UMat> &vec)
{
return vec_descr_of(vec);
}
#endif
cv::GMetaArgs cv::descrs_of(const std::vector<cv::Mat> &vec)
{
return vec_descr_of(vec);
}
cv::GMetaArgs cv::gapi::own::descrs_of(const std::vector<Mat> &vec)
{
return vec_descr_of(vec);
}
cv::GMatDesc cv::descr_of(const cv::RMat &mat)
{
return mat.desc();
}
namespace cv {
std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc)
{
switch (desc.depth)
{
#define TT(X) case CV_##X: os << #X; break;
TT(8U);
TT(8S);
TT(16U);
TT(16S);
TT(32S);
TT(32F);
TT(64F);
#undef TT
default:
os << "(user type "
<< std::hex << desc.depth << std::dec
<< ")";
break;
}
os << "C" << desc.chan;
if (desc.planar) os << "p";
os << " ";
os << desc.size.width << "x" << desc.size.height;
return os;
}
namespace {
template<typename M> inline bool canDescribeHelper(const GMatDesc& desc, const M& mat)
{
const auto mat_desc = desc.planar ? cv::descr_of(mat).asPlanar(desc.chan) : cv::descr_of(mat);
return desc == mat_desc;
}
} // anonymous namespace
bool GMatDesc::canDescribe(const cv::Mat& mat) const
{
return canDescribeHelper(*this, mat);
}
bool GMatDesc::canDescribe(const cv::RMat& mat) const
{
return canDescribeHelper(*this, mat);
}
}// namespace cv