这一节介绍一些图像处理的最基本的方法。
首先要声明一个类的对象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