OpenCV 2 学习笔记(4): 加载,显示和保存图像,Mat类与IplImage类

这一节介绍一些图像处理的最基本的方法。

首先要声明一个类的对象cv:Mat image; 他有一个方法size()可以返回图像的宽和高

std::cout << "size: " << image.size().height << " , "
          << image.size().width << std::endl;

接下来去读取图像,并且分配内存:

image=  cv::imread("img.jpg");

接下来就可以操作图像了,但是为了程序的严谨性,要考虑图像是否被正确读取:

if(!image.data)
{
//没有读取图像
}

成员变量data是一个指向包含图像数据内存块的指针。当没有读取图像是就被置为0。读取之后就需要显示图像,我们可以使用highgui模块中的方法,先创建一个窗口,然后将图像指定显示在这个窗口上:   

       cv::namedWindow("OriginalImage");
       cv::imshow("OriginalImage",image);

接下来可能就要处理这个图像。opencv提供了许多图像处理函数可供选择。首先我们从一个简单的说起,水平翻转图像。在opencv中许多图像可以原地转换,就是可以直接把结果作用在输入图像上,不用再输入新的图像。

       

       cv::Mat result;
       cv::flip(image,result,1);// positive for horizontal
                                // 0 for vertical,                   
                                // negative for both
       cv::namedWindow("OutputImage");
       cv::imshow("OutputImage", result);

因为控制台窗口在main程序结尾都会终止,我们使用highgui中方法去等待用户输入任意键结束程序。     

 cv::waitKey(0);

保存图像    

 cv::imwrite("output.bmp",result);

 文件后缀名会决定使用哪个解码器保存图像。

 在opencv C++接口中所有的类和函数都是使用cv命名空间。可以使用      

 usingnamespace cv;

这样就不需要cv::这个前缀。

Mat类是存储图像或者其他矩阵数据的类。通常情况下可以在初始化时指定大小:       

cv::Mat ima(240,320,CV_8U,cv::Scalar(100));

 这里CV_8是指一个像素占用一个字节,U表示是无符号的unsigned。同样有符号使用S。彩色图像使用CV_8UC3。还有其他CV_16SC3、CV_32F。

当Mat对象超出范围,分配内存自动释放。这可以避免内存泄漏。Mat类是使用引用计数,当图像赋值给另一个变量时,不用复制,只是将之指向相同的内存块,引用计数加一。当所有对图像引用取消时,内存才被释放,且只释放一次。如果你需要复制,使用copyto()方法。     

 cv::Mat image2, image3;
 image2=result; // the two images refer to the same data
 result.copyTo(image3);// a new copy is created

如果这时你旋转result图像,你会发现image2也旋转了,而image3没有改变,这就是上述的原因。

我们要避免下面这种情况       

classTest {
    // image attribute
    cv::Mat ima;
     public:
       //constructor creating a gray-level image
       Test() : ima(240,320,CV_8U,cv::Scalar(100)) {}
       // method return a class attribute, not agood idea...
      cv::Mat method() { return ima; }
}

因为如果我们使用method方法,返回一个ima浅复制。如果后来这个复制被改变了,类中ima属性也被改变了,这会影类的后续操作,反过来也是一样的。可以使用copyto()方法避免这种错误。

Opencv2使用的是新的C++接口。先前C结构的函数和结构体,特别是IplImage结构体,继承于IPL库(Intel Processing Library),为了方便以前代码可以照常使用,Opencv提供了Mat与之简单的转换方法;     

       IplImage* iplImage = cvLoadImage("c:\\img.jpg");
       cv::Mat image4(iplImage,false);

Image4第二个参数表示数据不会被复制。IplImage和image4会分享相同的图像数据。为了防止创建野指针(dangling pointers)。使用opencv2提供的引用指针计数类来封装IplImage类会比较安全些。     

 cv::PtriplImage = cvLoadImage("c:\\img.jpg");

否则的话,你需要手动释放IplImage结构体:   

 cvReleaseImage(&iplImage);

现在一般使用cv::Mat


你可能感兴趣的:(OpenCV,图像处理)