Opencv数据类型定义

时间:2013-06-13 12:17:24

标签: c++ opencv image-processing types

我想以一种聪明的方式访问opencv 2中的像素。为此,我定义了以下像素结构:

struct mypixels
{
    unsigned char red;
    unsigned char green;
    unsigned char blue;
};

现在我尝试了以下内容并且有效:

int sz[3] = {2,2};
cv::Mat XL(2,sz, CV_8UC3, cv::Scalar::all(0));
cv::Mat_<cv::Vec3b> pixiter = XL;
pixiter.at<mypixels>(0,0).green = 22;

现在这段代码在发布模式下运行良好,但在调试模式下,我遇到了访问冲突错误。我不想破解或重写opencv类。我只是想了解我应该做些什么来让这段代码在发布和调试模式下工作。 我想也许我应该像我在这里写的那样定义我的像素: http://docs.opencv.org/trunk/modules/core/doc/basic_structures.html#datatype 但我无法理解我应该在这里做什么或做什么。 也许这里有人知道更多。

- 编辑 -

使用user2151446的工作解决方案和一些额外的脑力我来到这个解决方案:

template<> class cv::DataType<mypixels>
{
public:
    typedef mypixels value_type;
    typedef int work_type;
    typedef unsigned char channel_type;
    typedef value_type vec_type;
    enum { depth = CV_8U, channels = 3,
           type = CV_MAKETYPE(depth, channels), fmt=(int)'u' };
};

3 个答案:

答案 0 :(得分:4)

您的代码在发布模式下“工作”的原因是禁用了以下断言:

template<typename _Tp> inline _Tp& Mat::at(int i0, int i1)
{
    CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
        (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
        CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
    return ((_Tp*)(data + step.p[0]*i0))[i1];
}

你可以在mypixels的定义之后添加它(虽然我不确定我推荐它):

template<> class DataType<mypixels>
{
public:
    typedef mypixels value_type;
    typedef int work_type;
    typedef value_type channel_type;
    typedef value_type vec_type;
    enum { depth = 1, channels = 3,
           type = CV_MAKETYPE(depth, channels) };
};

然后你可以这样做:

Mat_<mypixels>& M1 = (Mat_<mypixels>&)pixiter;
M1.at<mypixels>(0,0).green = 22;

答案 1 :(得分:2)

您应该在cv::Vec3b中使用pixiter.at<T>(row,col)类型作为模板参数。 由于您的自定义类型对应于cv::Vec3b oyu的定义,因此可以根据需要直接投射结果。

哦,顺便说一句,OpenCV的默认颜色排序是BGR。

答案 2 :(得分:0)

可能有两个问题。

  1. 确保您使用正确的发布模式二进制文件来运行该程序。

  2. 对于包含cv :: Vec3b类型元素的矩阵,使用mypixels模板化的迭代器的使用是不正确的。尽管它们是类似定义的类型,但它们不能被认为是相同的。

  3. 最干净的方式是

    int sz[3] = {2,2};
    cv::Mat XL(2,sz, CV_8UC3, cv::Scalar::all(0));
    cv::Mat_<cv::Vec3b> pixiter = XL;
    pixiter.at<cv::Vec3b>(0,0).val[1] = 22;
    

    如果你真的想以自己的方式做,你可以做这样的事情。但是,当OpenCV改变他们的数据结构时,这将会破裂,如果是偶然的话。

    int sz[3] = {2,2};
    cv::Mat XL(2,sz, CV_8UC3, cv::Scalar::all(0));
    cv::Mat_<cv::Vec3b> pixiter = XL;
    cv::Vec3b& aVec = pixiter.at<cv::Vec3b>(0,0);
    mypixels& aMyPixel = reinterpret_cast<mypixels&>(aVec);
    aMyPixel.green = 22;