我应该如何命名我的RGB通道,使用cv :: Mat_

时间:2012-11-07 14:51:37

标签: c++ opencv

我想以下列方式访问我的矩阵元素:

frame[i][j].Red  

,即第(i,j)个像素的红色通道。

我试过了:

typedef struct{unsigned char Blue,Green,Red;}Pixel;  
typedef cv::Mat_<Pixel> Image;

然而,当尝试使用imread(),imwrite()或其他具有这样定义的类型时,g ++会问我:

OpenCV Error: Assertion failed (func != 0) in convertTo, file /home/users/mvitkov/projects/opencv-legacy/OpenCV-2.3.1/modules/core/src/convert.cpp, line 937
terminate called after throwing an instance of 'cv::Exception'
    what():  /home/users/mvitkov/projects/opencv-legacy/OpenCV-2.3.1/modules/core/src/convert.cpp:937: error: (-215) func != 0 in function convertTo

更新:所以没有回答我可能提出的问题。太糟糕了。问题的实质是如何使用合理的名称(红色,绿色,bkue)来处理各个频道,而不是c-era数组索引符号[2]。杜!

2 个答案:

答案 0 :(得分:4)

以下是您访问每个频道的方式:

blue = frame.at<cv::Vec3b>(i,j)[0]; 
green = frame.at<cv::Vec3b>(i,j)[1]; 
red = frame.at<cv::Vec3b>(i,j)[2]; 

上面的代码假设您有一个3通道图像,其中每个值都是 8位无符号字符(CV_8UC3。此类型用于许多常见的图像格式。但是,如果您有不同类型的3通道图像,请执行以下操作:

  • 如果图片类型为3通道浮点数(CV_32FC3),则将cv::Vec3b替换为cv::Vec3f
  • 如果图片类型为3通道双倍(CV_64FC3),则将cv::Vec3b替换为cv::Vec3d
  • 如果图片类型为3渠道整数(CV_32SC3),则将cv::Vec3b替换为cv::Vec3i
  • 如果图片类型为3通道短int(CV_16SC3)或16位uchar(CV_16UC3),则将cv::Vec3b替换为cv::Vec3s

不确定您使用的是哪种图片格式?尝试拨打getImgType(frame)(请参阅下面的代码)。

string getImgType(cv::Mat frame)
{
    int imgTypeInt = frame.type();
    int numImgTypes = 28; // 7 base types, with 4 channel options each (C1, ..., C4)
    int enum_ints[] = {CV_8UC1,  CV_8UC2,  CV_8UC3,  CV_8UC4, CV_8SC1,  CV_8SC2,  CV_8SC3,  CV_8SC4, CV_16UC1, CV_16UC2, CV_16UC3, CV_16UC4, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, CV_32SC1, CV_32SC2, CV_32SC3, CV_32SC4, CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4};
    string enum_strings[] = {"CV_8U",  "CV_8UC1",  "CV_8UC2",  "CV_8UC3",  "CV_8UC4", "CV_8SC1",  "CV_8SC2",  "CV_8SC3",  "CV_8SC4", "CV_16UC1",  "CV_16UC2",  "CV_16UC3",  "CV_16UC4", "CV_16SC1", "CV_16SC2", "CV_16SC3", "CV_16SC4", "CV_32SC1", "CV_32SC2", "CV_32SC3", "CV_32SC4", "CV_32FC1", "CV_32FC2", "CV_32FC3", "CV_32FC4", "CV_64FC1", "CV_64FC2", "CV_64FC3", "CV_64FC4"};
    for(int i=0; i<numImgTypes; i++)
    {
        if(imgTypeInt == enum_ints[i]) return enum_strings[i];
    }
    return "unknown image type";
}

答案 1 :(得分:0)

  

如果图像类型是3通道短int(CV_16SC3)或16位uchar(CV_16UC3),则将cv :: Vec3b替换为cv :: Vec3s

这根本不正确。我用一个3通道16位无符号图像和&lt; Vec3s&gt;,得到负值G:29096 B:-21671 R:23413返回。

如果CV_16UC3,请使用&lt; Vec3w取代。使用这个我得到G:29096 B:43865 R:23413

CV_16SC3中的“s”代表签名而非短。