查看原文
其他

OpenCV中如何获取Mat类型中的步长stride及分析 C++实现

独步天秤 OpenCV学堂 2020-02-04

点击上方↑↑↑“OpenCV学堂”关注我

作者博客: https://blog.csdn.net/yl_best

问题需求:获取Mat stride

如题,需要使用到Mat类型的步长stride。


先从本地读取一张图片,单步进去看到srcImage的属性如下图,有stride,也有width,height,channels等

我们可以通过srcImage.cols或者srcImage.size().width来获取图片的宽度,

通过srcImage.channels()来获取通道数量,

通过srcImage.type()来获取图片类型


但是怎么获取图片的stride呢?

这两种方式

srcImage.stride
or
srcImage.stride()


都是不对的,编译器会报错

"Error:class "cv::Mat" has no member "stride",怎么办?

官方资料解释

去OpenCV头文件里只找到这一段话:【位于mat.hpp里】

So, the data layout in Mat is fully compatible with CvMat, IplImage, and CvMatND types from OpenCV

1.x. It is also compatible with the majority of dense array types from the standard toolkits and

SDKs, such as Numpy (ndarray), Win32 (independent device bitmaps), and others, that is, with any

array that uses *steps* (or *strides*) to compute the position of a pixel. Due to this

compatibility, it is possible to make a Mat header for user-allocated data and process it in-place

using OpenCV functions.

看起来stride就是step,那如何获取step?

如何获取stride

代码很简单,就这样一句话srcImage.step

深入分析

MatStep类型的结构体

但是如果F5单步进去看,会发现step其实是一个MatStep类型的结构体,如下:

这个结构体有两个成员,size_t * p和size_t buf[2].

struct CV_EXPORTS MatStep
{

    MatStep();
    explicit MatStep(size_t s);
    const size_toperator[](int i) const;
    size_toperator[](int i);
    operator size_t() const;
    MatStep& operator = (size_t s);

    size_t* p;
    size_t buf[2];
protected:
    MatStep& operator = (const MatStep&);
};



MatStep的构造函数

再单步进MatStep的构造函数如下:

inline
MatStep::MatStep()
{
    p = buf; p[0] = p[1] = 0;
}

inline
MatStep::MatStep(size_t s)
{
    p = buf; p[0] = s; p[1] = 0;
}


发现p指向buf,buf代表数组的首地址,二者指向的位置是一样的。在我的电脑上,都指向同一个地址0x00f5fdc4。继续单步,按F11 Step into,编译器就会带我们进入到以下这个函数


隐式类型转换的操作符重载函数

inline MatStep::operator size_t() const
{
    CV_DbgAssert( p == buf );
    return buf[0];
}


重点来了。。这个结构体重载了size_t的隐式类型转换,所以我们用srcImage.step就可以直接获取stride了。

运算符重载的知识

此处再回忆下运算符重载的知识


operator它有两种用法,

  • operator overloading(操作符重载)

  • operator casting(操作符隐式转换)

操作符重载:类型T operator 操作符 (参数)【举例:size_t& operator[] (int i)重载了[],参数是int i, 返回size_t &】操作符隐式转换:operator 类型T ()  【这里用的是这一种】


可以参考

《C++技巧之operator操作符》


都是很基本的东西,欢迎大家指正。


完整版代码

#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;  //包含cv命名空间
using namespace std;

int main(int argc, char ** argv)
{
Mat srcImage;
// 【1】读入一张图片,载入图像
srcImage = imread("F:/images/lena.jpg");     //在程序中打开一张图片
//Because of pop_back() and resize() methods `M.total() == 0` does not imply that `M.data == NULL`.
//if (!srcImage.data)   
if (srcImage.empty())
{
printf("could not load image...\n");
return -1;
}
cout << "srcImage.step is " << srcImage.step << endl;
cout << "srcImage.step[0] is " << srcImage.step[0] << endl;
unsigned int  x = srcImage.step;
char input_title[] = "input image";
namedWindow(input_title, CV_WINDOW_AUTOSIZE);
// 【2】显示载入的图片
imshow(input_title, srcImage);

// 【3】等待任意按键按下
waitKey(0);
return 0;
}

往期精选

告诉大家你 在看

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存