3

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

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]。呸!

4

2 回答 2

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::Vec3bcv::Vec3f
  • 如果图像类型是 3 通道双精度 ( CV_64FC3),则替换cv::Vec3bcv::Vec3d
  • 如果图像类型是 3-channel int ( CV_32SC3),则替换cv::Vec3bcv::Vec3i
  • 如果图像类型是 3-channel short int ( CV_16SC3) 或 16-bit uchar ( CV_16UC3),则替换cv::Vec3bcv::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";
}
于 2012-11-10T05:41:09.213 回答
0

如果图像类型为 3-channel short int (CV_16SC3) 或 16-bit uchar (CV_16UC3),则将 cv::Vec3b 替换为 cv::Vec3s

这根本不正确。我用 <Vec3s> 处理了一个 3 通道 16 位无符号图像,并得到一个负值 G:29096 B:-21671 R:23413 返回。

如果是 CV_16UC3,则使用 <Vec3w> 寻址 Mat。使用这个我得到了 G:29096 B:43865 R:23413

CV_16SC3 中的“s”代表有符号而不是短。

于 2014-08-25T08:22:38.367 回答