OpenCV Mat 到数组访问

Posted

技术标签:

【中文标题】OpenCV Mat 到数组访问【英文标题】:OpenCV Mat to array access 【发布时间】:2016-01-10 23:42:28 【问题描述】:

我在从 Mat.data 访问数据时遇到问题。我对图片执行操作,我需要分别访问每个像素。 我必须对简单类型(float、int 等)进行操作。 我访问数据的方式如下:

for (int idx = 0; idx < image.rows; idx++) 
        for (int idy = 0; idy < image.cols; idy++) 
            int color_tid = idx * image.cols * image.channels() + idy * image.channels();
            uint8_t blue = image.data[color_tid];
            uint8_t green = image.data[color_tid + 1];
            uint8_t red = image.data[color_tid + 2];
            float pixelVal = (int) blue + (int) green + (int) red;
            (...)
        
    

这种方法仅适用于正方形图像(NxN 像素),但对于 NxM,在正方形区域(较小的边缘)之外存在异常。 有谁知道访问图片 Mat 数据的任何其他方式? 示例图片(正确结果):

异常(我的问题)

【问题讨论】:

没有看到你所有的代码,很难知道发生了什么。但是,在您的循环中,您可以只写:Vec3b v = image(row, col); float pixelVal = v[0] + v[1] + v[2];。还要记住 rowsy 坐标,而 colsx。所以你可能一开始只是交换了你的索引。 Vec3b v 不是简单类型...我必须使用 image.data 必须....是作业还是什么? 嗯,我想跳过上下文。我必须使用简单类型,因为代码在 Cuda 中使用。我发送到设备数组 image.data 因为我不能使用 Mat 函数。 【参考方案1】:

我建议在Mat 中关注data layout

所以你的循环变成:

for (int r = 0; r < img.rows; ++r)

    for (int c = 0; c < img.cols; ++c)
    
        uchar* ptr  = img.data + img.step[0] * r + img.step[1] * c;
        uchar blue  = ptr[0];
        uchar green = ptr[1];
        uchar red   = ptr[2];

        float pixelVal = blue + green + red;
    

您最终可以执行更少的操作,例如:

for (int r = 0; r < img.rows; ++r)

    uchar* pt = img.data + img.step[0] * r;
    for (int c = 0; c < img.cols; ++c)
    
        uchar* ptr  = pt + img.step[1] * c;
        uchar blue  = ptr[0];
        uchar green = ptr[1];
        uchar red   = ptr[2];

        float pixelVal = blue + green + red;
    

【讨论】:

感谢回复,但您的方法会产生与我相同的问题。明天我会详细检查它,如果是完全相同的问题会写出来 @jak5z 这工作正常,还可以处理非连续矩阵。但是您的方法在连续矩阵上运行良好,所以我敢打赌,问题在于您如何传递数据。同样,没有minimal reproducible example,很难说。 我没有使用这个方法,但我知道没问题。谢谢【参考方案2】:

您问题中的代码存在一些缺陷:

行列交换(行为Y,列为X) 行间步长(又称“步幅”)并不总是等于列数

使用Mat::at&lt;&gt; 使代码更简单:

 for(int row = 0; row < image.rows; ++row)
 
     for(int col = 0; col < image.cols; ++col)
     
         const Vec3b& pt = image.at<Vec3b>(row, col);
         float pixelVal = pt[0] + pt[1] + pt[2];
         ...    
        
  

【讨论】:

const Vec3b& pt = image.at(row, col);不是简单的类型...我必须使用 image.data @jak5z:Miki 的解决方案也应该适合您。我很惊讶它没有。

以上是关于OpenCV Mat 到数组访问的主要内容,如果未能解决你的问题,请参考以下文章

《OpenCV:访问Mat图像中每个像素值》

【OPENCV】cv::Mat像素遍历方法比较

将我的数组移动到 Mat 并使用 openCV 显示图像

使用 OpenCV 多通道 Mat 沿通道方向访问像素

用于 OpenCv C++ 中像素像素操作的 Mat 与数组

OpenCV Mat 到 alglib 真实二维数组的转换