OpenCV控制摄像头实现 拍照功能
注意注释部分,其中使用的比较生疏的 API 包括 cvPyrDown , cvCreateCameraCapture
以及 cvCopy 和 cvSaveImage
下面就来一一解释这几个 API 的具体使用:
void cvPyrDown( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 );
其中 src 为 CvArr * 类型,这里顺便解释一下 OpenCV 基本上是用 C 实现的,当然其中包括一定的 C++ 成分,
但是 OpenCV 中仍然也使用了面向对象的思想,即有以下的继承关系:
所以在实际使用当中,完全可以使用 ”子类” CvMat 或者是 IplImage 来代替 CvArr ,
也就是说在参数中完全可以传入一个 IplImage 类型,
src 代表的就是源图像,即传入函数的图像,而 dst 则是输出图像,即缩放一倍后的图像,
但是需要注意的是,在这里传入的 dst 图像必须是在初始化以后才能传入,
对于这一点,在下面的 Demo 中可以看到。而至于卷积滤波器的类型则一般采用默认类型即可。
CvCapture* cvCreateCameraCapture( int index );
大伙应该还记得 cvCreateFileCapture 这个函数吗?
其实对于 cvCreateFileCapture 来说,其是根据一个指定的视频文件来初始化,
而对于 cvCreateCameraCapture 则不同,其是通过初始化一个视频设备 (也可以看做就是一个摄像头),
初始化以后,便可以从这个摄像设备中获取视频了。
至于参数 index 的话,如果您的电脑上连接了多个摄像设备,则需要通过这个 index 来指定到底要使用哪一个摄像头。
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
这个函数的作用是拷贝一个数组到另一个数组,而根据前面的继承关系,IplImage 继承自 CvMat,
而 CvMat 又是继承于 CvArr ,所以在此处可以直接传入一个 IplImage 来实现拷贝,
很明显,src 是传入的数组,而 dst 则是复制完成后返回的结果数组,
而至于 mask 这个数组呢,比较变态,
它指定了数组 src 中哪些元素需要拷贝到 dst 数组中,哪些元素不能够拷贝到 dst 数组中,
mask 数组中标记为非 0 的则可以拷贝到 dst 中,标记为 0 的则不会拷贝到 dst 数组当中去。
这里需要注意的是,dst 数组和 src 数组必须是相同的类型,并且具有相同的维数和大小,否则整个程序会崩溃。
int cvSaveImage( const char* filename, const CvArr* image );
这个函数的作用很明显,即保存图片到文件,而至于保存的图片的文件则看 filename 这个参数指定的后缀名是什么了。
#include "stdafx.h" #include"cv.h" #include"highgui.h" #include"stdio.h" // 实现将拍下来的图片缩放一倍 IplImage* DoPyrDown(IplImage* image, int filter = IPL_GAUSSIAN_5x5) { // 设置大小缩小一倍 CvSize size = cvSize(image->width / 2,image->height / 2); //初始化图片 IplImage* outImage = cvCreateImage(size,image->depth,image->nChannels); //实现缩放 cvPyrDown(image,outImage); cvReleaseImage(&image); return outImage; } int main(int argc, char** argv) { cvNamedWindow("vedio"); CvCapture* capture; // 首先是要通过摄像设备来得到一个CvCapture对象 if(1 == argc) { capture = cvCreateCameraCapture(0); } else { capture = cvCreateCameraCapture(atoi(argv[1])); } assert(NULL != capture); IplImage* frame; char keyCode; // 每隔30ms捕捉一次视频图像 // 可以设为while(1) 使得实时捕捉视频画面 while((keyCode = cvWaitKey(30))) { //表示按下了ESC键,退出 if(keyCode == 27) { break; } //表示按下了回车键,此时应当保存照片 if(keyCode == 13) { //初始化一张图片 IplImage* outImage = cvCreateImage(cvGetSize(frame),frame->depth,frame->nChannels); // 将原图拷贝过来 cvCopy(frame,outImage,NULL); //实现缩放操作 outImage = DoPyrDown(outImage); //设置保存的图片名称和格式 char* outImageName = "test.jpg"; //保存图片 cvSaveImage(outImageName,outImage); cvReleaseImage(&outImage); printf(" 恭喜你,保存图片成功!\n"); } // 得到摄像设备的下一帧图像 frame = cvQueryFrame(capture); if(!frame) { break; } cvShowImage("vedio",frame); } cvReleaseImage(&frame); cvDestroyAllWindows(); return 0; }
F5执行结果:F5执行结果:结果: