无法访问类型为 16UC(6) 的 6 通道垫

Unable to access 6 channel Mat of type 16UC(6)

我无法访问 16UC(6) 类型的垫子。下面是用于迭代 Mat 的代码。

//6 channel Mat
int cols=1280, rows=720;
Mat mat1=Mat(cols, rows, CV_16UC(6), Scalar::all(0));
Mat grid(Size(cols, rows), CV_16UC2, Scalar::all(0));   
//create a grid of numbers - the value of each pixel in the grid 
contains the coordinate of the pixel
for (int i = 0; i < grid.rows; ++i) {
    for (int j = 0; j < grid.cols; ++j) {
        grid.at<Vec2s>(i, j)[0] = (ushort)j;
        grid.at<Vec2s>(i, j)[1] = (ushort)i;
    }
}
vector<Mat> imgs(2); //create copies of the grid for each image
for(int i=0;i<2;i++){
    imgs[i] = grid.clone();
}
//Values in Mat1 are filled with values of imgs[0] and imgs[1] using 
// some logic.
int rows=mat1.rows;
int channels=mat1.channels();
int cols=mat1.cols * channels;
uchar* p;
for(int i=0;i<rows;i++){
   p=mat1.ptr<uchar>(i);
   for(int j=0;j<cols;j+=6){
      cout<<"Value 0 :"<<p[j]<<endl;
      cout<<"Value 1 :"<<p[j+1]<<endl;
      cout<<"Value 2 :"<<p[j+2]<<endl;
      cout<<"Value 3 :"<<p[j+3]<<endl;
      cout<<"Value 4 :"<<p[j+4]<<endl;
      cout<<"Value 5 :"<<p[j+5]<<endl;
   }
 }

但我得到 ^E 和 ^@ 作为值。当尝试转换为 (int) 时,我得到的都是零。 我可以使用 MatIterator 正确访问 Mat。我不确定哪里出错了,Mat 类型和我尝试访问 value.Can 的方式肯定有问题,任何人都可以帮助我解决问题。

你有:

grid.at<Vec2s>(i, j)[0] = (ushort)j;

Vec2s 用于短裤,但您有 Unsigned Short 矩阵。您应该使用 Vec2w(不知道是谁带了 w... 或为什么)用于无符号短。

这可以重写为:

grid.at<cv::Vec2w>(i, j)[0] = static_cast<ushort>(j);

然后,显示 16U 矩阵的 uchar 值...每个 uchar 为 8 位,每个像素为 16 位...

这是一个示例,说明如何使用 CV_16UC(6) 矩阵中的迭代器访问每个像素。

  // create dummy 3x3 matrix
  cv::Mat b(3,3,CV_16UC(6));
  // use the templated functions begin and end (you may templated with <ushort> 
  // directly and it will represent the value of each channel of each pixel)
  for (auto it = b.begin<cv::Vec<ushort, 6>>(); it != b.end<cv::Vec<ushort, 6>>(); ++it)
  {
    // assign some values (this part can be skipped if it is already filled)
    (*it)[0] = 5;
    (*it)[1] = 7;
    (*it)[2] = 8;
    (*it)[3] = 9;
    (*it)[4] = 1;
    (*it)[5] = 2;
    // Print the Vec<ushort, 6>, OpenCV already has a way to print it
    std::cout << *it << std::endl;
  }

而这段小代码的结果是:

[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]

这是我们所期望的。您可能已经注意到,我使用 cv::Vec<ushort, 6>,cv::Vec 可以用任意数量的通道(可能有限制)和任何类型(我只用原生数字类型测试过)进行模板化。实际上 cv::Vec2wcv::Vec2s 分别只是 cv::Vec 和 cv::Vec 的 typedef,如果你在整个代码中使用它,你也可以创建你的 typedef。

using Vec6w = cv::Vec<ushort, 6>;

然后你可以在for循环中替换它:

...
for (auto it = b.begin<Vec6w>(); it != b.end<Vec6w>(); ++it)
...

并取得相同的结果