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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法访问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 ype和我试图获取价值的方式一定存在问题。任何人都可以帮助我解决问题。

答案

你有:

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

Vec2s用于短裤,但你有无符号短矩阵。你应该使用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)
...

并实现相同的结果

以上是关于无法访问16UC类型的6通道垫的主要内容,如果未能解决你的问题,请参考以下文章

如何正确将 cv::Mat 转换为 CV_8UC1?

OpenCV 填充垫,与 VideoWriter 一起使用

学习opencv

如何将 cv::Mat 类型从 CV_16UC1 转换为 CV_8UC1

opencv矩阵运算

CV_8UC1,CV_8UC2,CV_8UC3等意思