Mat类对象的分析与应用


1 Mat对象的构造方法

Mat类提供了构造函数、复制构造函数与赋值构造函数来初始化一个对象。下面选取了Opencv中的部分源代码:

 

 1  //! default constructor
 2     Mat();
 3     //! constructs 2D matrix of the specified size and type
 4     // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
 5     Mat(int rows, int cols, int type);
 6     Mat(Size size, int type);
 7     //! constucts 2D matrix and fills it with the specified value _s.
 8     Mat(int rows, int cols, int type, const Scalar& s);
 9     Mat(Size size, int type, const Scalar& s);
10 
11     //! constructs n-dimensional matrix
12     Mat(int ndims, const int* sizes, int type);
13     Mat(int ndims, const int* sizes, int type, const Scalar& s);
14 
15     //! copy constructor
16     Mat(const Mat& m);
17     //! constructor for matrix headers pointing to user-allocated data
18     Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
19     Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
20     Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0);
21 
22     //! creates a matrix header for a part of the bigger matrix
23     Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all());
24     Mat(const Mat& m, const Rect& roi);
25     Mat(const Mat& m, const Range* ranges);
26     //! converts old-style CvMat to the new matrix; the data is not copied by default
27     Mat(const CvMat* m, bool copyData=false);
28     //! converts old-style CvMatND to the new matrix; the data is not copied by default
29     Mat(const CvMatND* m, bool copyData=false);
30     //! converts old-style IplImage to the new matrix; the data is not copied by default
31     Mat(const IplImage* img, bool copyData=false);
32     //! builds matrix from std::vector with or without copying the data
33     template<typename _Tp> explicit Mat(const vector<_Tp>& vec, bool copyData=false);
34     //! builds matrix from cv::Vec; the data is copied by default
35     template<typename _Tp, int n> explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true);
36     //! builds matrix from cv::Matx; the data is copied by default
37     template<typename _Tp, int m, int n> explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true);
38     //! builds matrix from a 2D point
39     template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true);
40     //! builds matrix from a 3D point
41     template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true);
42     //! builds matrix from comma initializer
43     template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);
44 
45     //! download data from GpuMat
46     explicit Mat(const gpu::GpuMat& m);
47 
48     //! destructor - calls release()
49     ~Mat();
50     //! assignment operators
51     Mat& operator = (const Mat& m);
52     Mat& operator = (const MatExpr& expr);

 

我们可以采用上述函数构造Mat对象,如

1 Mat A, C;   //缺省构造函数,只创建了头部分,没有实际数据
2 A = imread("1.jpg", CV_LOAD_IMAGE_COLOR);//将图片1数据读入A中
3 Mat B(A);        //使用复制构造函数使B指向A的数据
4 C=A;              //使用赋值构造函数使C指向A的数据
5 Mat D(2,2, CV_8UC3, Scalar(0,0,255))  //利用带参数的构造函数创建对象

Mat对象采用了引用计算的方法,A,C,B只是头不同,但都指向相同的数据,每当复制一个Mat对象的头时,引用计数加1,当清除一个头时,引用计数减1,当引用计数为0时,释放资源。为了复制数据,可以采用Mat类中的clone()copyTo()方法。

2 用Mat类中的方法处理图像

利用at方法改变图像中每一个位置的像素值

 

Process(Mat & image)
{
for(int i=0;i<image.rows;i++)
for(int j=0;j<image.cols;j++)
{
if (image.channels() == 1) { // gray-level image image.at<uchar>(j,i)= 255; } else if (image.channels() == 3) { // color image image.at<cv::Vec3b>(j,i)[0]= 255; image.at<cv::Vec3b>(j,i)[1]= 255; image.at<cv::Vec3b>(j,i)[2]= 255; }
} }

 

利用ptr方法可以进行同样的操作

Process(Mat & image)
{  
   int row=image.rows;
   int cn=image.cols*image.channel();//每一行的数据
   for(int i=0;i<row;i++)
  {
      //得到第i行的地址
     uchar* data= image.ptr<uchar>(j);
     for(int j=0;j<cn;j++)
     {
       data[j]=255;
     }
  }
}

 使用迭代器

Process(Mat & image)
{ 
if (image.channels() == 1) { // gray-level image Mat_<uchar>::iterator it=image.begin<uchar>();
Mat_<uchar>::iterator itend=image.end<uchar>();
for(;it!=itend;it++)
*it=255; }
else if (image.channels() == 3) { // color image Mat_<Vec3b>::iterator it=image.begin<Vec3b>();
Mat_<Vec3b>::iterator itend=image.end<Vec3b>();
for(;it!=itend;it++)
{
(*it)[0]=255;
(*it)[1]=255;
(*it)[2]=255;
}

}
}

利用邻域像素点作处理,如图像的锐化

void sharpen(const cv::Mat &image, cv::Mat &result) 
{
// allocate if necessary result.create(image.size(), image.type()); for (int j= 1; j<image.rows-1; j++)
{
const uchar* previous= image.ptr<const uchar>(j-1); // 前一行 const uchar* current= image.ptr<const uchar>(j); // 当前行 const uchar* next= image.ptr<const uchar>(j+1); // 下一行 uchar* output= result.ptr<uchar>(j); // 输出行 for (int i=1; i<image.cols-1; i++)
{
*output++= cv::saturate_cast<uchar>( 5*current[i]-current[i-1] -current[i+1]-previous[i]-next[i]); } } // 将未处理的像素设为0 result.row(0).setTo(cv::Scalar(0)); result.row(result.rows-1).setTo(cv::Scalar(0)); result.col(0).setTo(cv::Scalar(0)); result.col(result.cols-1).setTo(cv::Scalar(0)); }

上述过程实际是利用一个3×3的模板对原始图像作卷积,opencv中的函数filter2D可以实现该过程

void sharpen2D(const cv::Mat &image, cv::Mat &result) 
{
// 创建卷积核 cv::Mat kernel(3,3,CV_32F,cv::Scalar(0)); // 设置卷积核的值 kernel.at<float>(1,1)= 5.0; kernel.at<float>(0,1)= -1.0; kernel.at<float>(2,1)= -1.0; kernel.at<float>(1,0)= -1.0; kernel.at<float>(1,2)= -1.0; //实现卷积计算 cv::filter2D(image,result,image.depth(),kernel); }

 

 
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告