OpenCV开发包分五个模块,其中,HighGUI包含图像和视频的输入输出函数。接下来主要讲这部分内容。
首先,图像和视频的现实需要创建一个窗口
cvNamedWindow(“Window Title”, WINDOW_SIZE);
第一个参数是窗口的标题,第二个参数是窗口的属性,可以被设置为0或者CV_WINDOW_AUTOSIZE,前者是说窗口固定大小,而后者窗口会根据图像的实际大小自动拉伸和缩放。
当然,既然有创建,就要有销毁
cvDestroyWindow(“Window Title”);
关闭窗口并释放所有的相关内存。
OpenCV中有一个结构体IplImage,用于存储图片的相关信息。通过IplImage* img = cvLoadImage(“File Name”),将图片的信息读取到IplImage中,然后调用cvShowImage(“Window Title”, img),显示图像。
最后当然也需要释放图像信息:
cvReleaseImage(&img);
源程序的代码如下:
#include "highgui.h" int main() { IplImage* img = cvLoadImage("test.jpg"); cvNamedWindow("TestImage",CV_WINDOW_AUTOSIZE); cvShowImage("TestImage", img); cvWaitKey(0); cvReleaseImage(&img); cvDestroyWindow("TestImage"); return 0; }
cvWaitKey(time)是暂停程序,等待用户触发一个按键操作。time是整数值,以毫秒为单位。
与图片类似,OpenCV将视频读取到CvCapture结构体中。
CvCaptuer* capture = cvCreateFileCapture(“File Name”);
值得注意的是,该函数只能读取固定格式的AVI文件,起初我选择的一些AVI格式并不能被OpenCV解码,于是返回的指针都是NULL。网上说下载VitualDub,我下载后发现我的AVI格式不对无法转换。
在电脑里翻翻找找半天,总算找到一个能转换的AVI文件,不过转换成未压缩的AVI文件是非常占空间的,我转了一会儿就提示空间不足了。现在重新转了个3分半的,3G多。
然后需要从capture中读取每一帧的图像信息,分别显示出来。使用这个函数img = cvQueryFrame(capture),然后用上面的显示图像的方法。
源代码如下:
#include "highgui.h" int main() { cvNamedWindow("Test Vedio",CV_WINDOW_AUTOSIZE); CvCapture* capture = cvCreateFileCapture("test.avi"); IplImage* frame; while(1) { frame = cvQueryFrame(capture); if(!frame) break; cvShowImage("Test Vedio", frame); char c = cvWaitKey(33); if(c == 27) break; } cvReleaseCapture(&capture); cvDestroyWindow("Test Vedio"); }
这里并不需要释放图像信息,因为会在视频信息释放的时候自动进行。这里固定了帧率是33,实际上,更好的方法是从CvCapture中读取。
接下来加入OPENCV的滚动条,使之能够通过拖动来控制视频播放。原本书上的代码并没有加入播放时自动调整滚动条的功能,并且使用的是硬编码的帧率,我在这里做了点修改。
#include "highgui.h" int g_slider_position = 0; CvCapture* g_capture = NULL; void onTrackbarSlide(int pos) { cvSetCaptureProperty(g_capture, CV_CAP_PROP_POS_FRAMES,pos); } int main() { cvNamedWindow("Test Vedio Slide",CV_WINDOW_AUTOSIZE); g_capture = cvCreateFileCapture("test.avi"); int frames = (int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT); int frameRate = (int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FPS); if(frames!=0) { cvCreateTrackbar("position","Test Vedio Slide", &g_slider_position, frames, onTrackbarSlide); } IplImage* frame; for(g_slider_position = 0;g_slider_position<frames;g_slider_position++) { frame = cvQueryFrame(g_capture); if(!frame) break; cvShowImage("Test Vedio Slide", frame); char c = cvWaitKey(frameRate); cvSetTrackbarPos("position","Test Vedio Slide", g_slider_position); onTrackbarSlide(g_slider_position); if(c == 27) break; } cvReleaseCapture(&g_capture); cvDestroyWindow("Test Vedio Slide"); }
首先注册一个回调函数,表示当拖动滚动条时会发生什么行为,在void onTrackbarSlide(int pos)中可以看到,是设置视频当前播放帧为pos。
然后通过读取视频属性,获取帧数量和FPS,创建一个滚动条cvCreateTrackbar("position","Test Vedio Slide", &g_slider_position, frames, onTrackbarSlide);其中position是滚动条的名字,这个函数顺便捆绑了回调函数onTrackbarSlide与函数参数g_slider_position。
在循环里,我添加了一句cvSetTrackbarPos("position","Test Vedio Slide", g_slider_position); 就可以自动设置滚动条的位置了。
但感觉还是不好用,毕竟OPENCV的重点不是图形控件。。。
接下来是平滑图像,其实只有一句话的内容,那就是cvSmooth(in,out,CV_GAUSSIAN,3,3);基本相当于PS里面的高斯模糊吧,技术点说,就是用一个3*3大小的区域对图像像素进行卷积操作。。。。
int main() { IplImage* img = cvLoadImage("test.jpg"); cvNamedWindow("TestImage-in",CV_WINDOW_AUTOSIZE); cvNamedWindow("TestImage-out",CV_WINDOW_AUTOSIZE); cvShowImage("TestImage-in", img); IplImage* out = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3); cvSmooth(img, out, CV_GAUSSIAN,3,3); cvShowImage("TestImage-out",out); cvWaitKey(0); cvReleaseImage(&img); cvReleaseImage(&out); cvDestroyWindow("TestImage-in"); cvDestroyWindow("TestImage-out"); return 0; }
基本到这里吧,复杂点的变换下次再看。。。
本文原创,转载请注明出处