初探opencv:数据结构Mat

Mat

属性简介

这是最常用的一个类,基本上图像都保存成Mat。
Mat(int rows, int cols, int type, const Scalar& s);
rows就是行数,cols就是列数,type代表的是类型。opencv定义了这么几种类型的方式是:CV_【位数】【类型】【C】【通道数】。比如CV_8UC1就是8位无符号单通道类型的。所谓通道数(channels)就是一个像素由几个数组成,比如最常用的RGB,就是三通道的彩图嘛。Scalar代表颜色。

访问元素一般方法

src.at<数据类型>(i,j,k) 只可读
src.ptr<数据类型>(i,j)[k] 可读可写
其中 i是行,j是列 , k是通道。注意,坐标的x是列,y是行。
当然还有STL风格的访问方式。更确切来说是一种遍历方式

MatConstIterator_<VT> it1 = src1.begin<VT>(), it1_end = src1.end<VT>();
            MatConstIterator_<VT> it2 = src2.begin<VT>();
            MatIterator_<VT> dst_it = dst.begin<VT>();

            for( ; it1 != it1_end; ++it1, ++it2, ++dst_it )
            {
                VT pix1 = *it1, pix2 = *it2;
                float alpha = pix1[3]*inv_scale, beta = pix2[3]*inv_scale;
                *dst_it = VT(saturate_cast<T>(pix1[0]*alpha + pix2[0]*beta),
                             saturate_cast<T>(pix1[1]*alpha + pix2[1]*beta),
                             saturate_cast<T>(pix1[2]*alpha + pix2[2]*beta),
                             saturate_cast<T>((1 - (1-alpha)*(1-beta))*alpha_scale));
            }

foreach操作

如果对每个像素要进行相同的操作且代码比较少,可以用forEach函数,推荐使用lambda表达式,例子如下。

        // Parallel execution using C++11 lambda.
        image.forEach<Pixel>([](Pixel &p, const int * position) -> void {
            p.x = 255;
        });

代码中const int* position 函数中没用到,但是有些编译器没有这玩意就是报错。

浅拷贝和深拷贝

由于Mat占用内存大,有时候我们不需要完全复制一个对象,而只是引用它或者它的某一部分。

Mat& operator = (const Mat& m);//浅拷贝
Mat rowRange(int startrow, int endrow) const;//和原来的是共享内存的
Mat colRange(int startcol, int endcol) const;
Mat operator()( const Rect& roi ) const;//感兴趣的矩形区域

有时候,我们需要一个拥有独立内存的对象。

Mat& operator = (const MatExpr& expr); //深拷贝

这里要说一下,MatExpr是一个运算表达式的类,计算结果返回的就是这个类型。比如C=A+B,这种。MatExpr赋值给Mat 都是深拷贝。如果是一个Mat想深拷贝给另一个Mat,请用

Mat clone() const;
void copyTo( OutputArray m ) const;

这两个函数都会自动创建内存空间。所以初始化Mat的时候注意了,如果你想用3个不同的Mat但是它们的Size是一样的,例如 R G B 三个通道。千万不要这样写:

Mat R(3,3,CV_8UC1); //错误例子
Mat G = R;
Mat B = R;

这样一搞,其实就只有一个Mat。

猜你喜欢

转载自blog.csdn.net/qq_16952303/article/details/76862778