OpenCV InputArray和getMat方法

时间:2014-03-03 17:09:43

标签: c++ opencv

我花了很多时间用cv::Matcv::Veccv::InputArray看起来很奇怪。

如果我将cv::EM定义为SampleTypecv::Vec并将cv::Matx定义为SampleContainerType,则

cv::Mat_需要和InputArray只有1个频道并填充它,一切正确,m_Samples具有正确的结构和1个通道。当样本以InputArray到达EM em.cpp#L83时,它会神奇地变为2个通道矩阵。

我想使用cv::Matxcv::Vec代替cv::Mat,以便用户轻松定义SampleType(1., 2.)等样本

我创建了这个文件https://gist.github.com/jrdi/9328183来测试组合,我不明白前两种方法有什么问题。另外,我不想像上一个例子那样重新创建每个样本。

修改(按要求添加代码):

#include "opencv2/core/core.hpp"
#include "itkObject.h"
#include "itkObjectFactory.h"

#include "BoostTestTargetConfig.h"

void CheckInputArrayChannels( cv::InputArray samples )
{
  cv::Mat matrix = samples.getMat();
  if( matrix.channels() != 1 )
  {
    itkGenericExceptionMacro( << "Channels error." );
  }
}

BOOST_AUTO_TEST_CASE( cxInputArrayTest )
{
  const unsigned int Dimension = 2;
  typedef double CoordinateType;
  // FAILS
  {
    typedef cv::Vec<CoordinateType, Dimension> SampleType;
    typedef cv::Mat_<CoordinateType>           SampleContainerType;

    SampleType sample(2., 1.);
    SampleContainerType samples;
    samples.push_back( sample.t() );

    BOOST_CHECK( samples.channels() == 1 );
    BOOST_CHECK_NO_THROW( CheckInputArrayChannels( samples ) );
  }
  // FAILS
  {
    typedef cv::Matx<CoordinateType, 1, Dimension> SampleType;
    typedef cv::Mat_<CoordinateType>               SampleContainerType;

    SampleType sample(2., 1.);
    SampleContainerType samples;
    samples.push_back( sample );

    BOOST_CHECK( samples.channels() == 1 );
    BOOST_CHECK_NO_THROW( CheckInputArrayChannels( samples ) );
  }
  // FAILS
  {
    typedef cv::Matx<CoordinateType, 1, Dimension> SampleType;
    typedef std::vector<SampleType>                SampleContainerType;

    SampleType sample(2., 1.);
    SampleContainerType samples;
    samples.push_back( sample );

    BOOST_CHECK_NO_THROW( CheckInputArrayChannels( samples ) );
  }
  // PASS
  {
    cv::Mat sample(1, 2, cv::DataType<CoordinateType>::type);
    sample.at<CoordinateType>(0) = 2.;
    sample.at<CoordinateType>(1) = 1.;

    cv::Mat_<CoordinateType> samples;
    samples.push_back( sample );

    BOOST_CHECK( samples.channels() == 1 );
    BOOST_CHECK_NO_THROW( CheckInputArrayChannels( samples ) );
  }
  // PASS
  {
    typedef cv::Matx<CoordinateType, 1, Dimension> SampleType;
    typedef cv::Mat_<CoordinateType>               SampleContainerType;

    SampleType sample(2., 1.);
    SampleContainerType samples;
    samples.push_back( cv::Mat(sample) );

    BOOST_CHECK( samples.channels() == 1 );
    BOOST_CHECK_NO_THROW( CheckInputArrayChannels( samples ) );
  }
}

1 个答案:

答案 0 :(得分:0)

来自OpenCV参考: -

Vec: Template class for short numerical vectors, a partial case of Matx.
...
The Vec class is commonly used to describe pixel types of multi-channel arrays

因此,当您将cv::Vec推送到Mat时,您正在制作多渠道行。

你的最后一个例子是创建多维矩阵的正确方法。 默认情况下,使用

时将复制数据
cv::Mat(sample)

您可以通过将sample传递给false构造函数来创建对Mat的引用。

cv::Mat(sample, false)

有关如何计算通道数的更多参考(行*列): -

template<typename _Tp, int m, int n> class Matx
{
public:
    typedef _Tp value_type;
    typedef Matx<_Tp, (m < n ? m : n), 1> diag_type;
    typedef Matx<_Tp, m, n> mat_type;
    enum { depth = DataDepth<_Tp>::value, rows = m, cols = n, channels = rows*cols,
       type = CV_MAKETYPE(depth, channels) };
  ....
 };