前言
在前文中给出了一个非常简短的视频播放程序,但它没有实现常规视频播放器中的播放滚动条功能,本文对此视频播放器程序加以改进,实现此功能。
滚动条的实现思路
滚动条的功能实质上就是从一帧跳跃到另外一帧,它的实现框架大致是这样的:
1. 首先要定义一个全局变量,在每次滚动条位置发生改变时将新的位置记录下来。
2. 然后定义一个回调函数 ,这个回调函数会在滚动条位置发生改变时自动执行。本文的程序中,回调函数具体的作用就是把程序的当前帧序更新为 1 中获取到的新的帧序。
3. 获取当前的总帧数。
4. 以 2 和 3 中获取到的结果等信息为参数,创建一个滚动条。
至此,滚动条功能就创建好了,别忘了,本文程序可是要求滚动条随着视频的播放而自动推进的。
代码示例
1 // 此头文件包含图像IO函数的声明 2 #include "highgui.h" 3 // 此头文件包含基本的图像处理函数和高级计算机视觉算法 4 #include "cv.h" 5 6 // 滚动条初始位置 7 int g_slider_position = 0; 8 // 视频结构体 9 CvCapture * g_capture = NULL; 10 // 当前帧序 11 int frameCur = 0; 12 13 void onTrackbarSlide (int pos) { 14 15 // 设置视频结构体的相关属性 16 cvSetCaptureProperty ( 17 g_capture, // 视频结构体 18 CV_CAP_PROP_POS_FRAMES, // 以帧为单位计量 19 pos // 新的位置 20 ); 21 // 更新当前帧序 22 frameCur = pos; 23 } 24 25 int main (void) { 26 27 // 定义一个窗口来播放视频 28 cvNamedWindow ("示例", CV_WINDOW_AUTOSIZE ); 29 30 // 将 D 盘目录下名为" 1.avi "的视频加载至内存并获得一个指向该视频内存块的指针,将它返回给 g_capture 31 // 该指针所指向的结构包含了此视频的当前播放帧序 32 g_capture = cvCreateFileCapture ("D:\1.avi"); 33 34 // 获取视频文件的总帧数 35 // 第一个参数为视频结构体;第二个参数为需要获取的属性标识( 本例为总帧数 ) 36 int frames = (int) cvGetCaptureProperty ( 37 g_capture, 38 CV_CAP_PROP_FRAME_COUNT 39 ); 40 41 // 创建滚动条 42 // 第一个参数为滚动条标题;第二个参数为滚动条所在窗口名;第三个参数为初始滑块位置 43 // 第四个参数为滑块总帧数;第五个参数为当滚动条发生改变时要调用的回调函数。 44 if (frames != 0) { 45 cvCreateTrackbar ( 46 "位置", 47 "示例", 48 &g_slider_position, 49 frames, 50 onTrackbarSlide 51 ); 52 } 53 54 // 定义一个图像指针来指向各帧图像 55 IplImage *frame; 56 57 while (1) { 58 59 // 获取视频最新的帧图。这个帧图是存放在视频内存块里的,因此,程序结束时只释放 capture 所指向的内存块就够了。 60 frame = cvQueryFrame (g_capture); 61 62 // 更新滚动条位置 63 cvSetTrackbarPos( 64 "位置", // 滚动条所在窗口 65 "示例", // 滚动条标题 66 frameCur++ // 滚动条位置 67 ); 68 69 // 读取帧失败则退出程序 70 if (!frame) break; 71 72 // 显示最新获取到的帧图 73 cvShowImage ("示例", frame); 74 75 // 用户键入ESC后退出循环,键入其他按键播放下一帧,什么都不按则 33 毫秒之后自动播放下一帧。 76 char c = cvWaitKey(33); 77 if (c==27) break; 78 }; 79 80 // 释放空间 81 cvReleaseCapture (&g_capture); 82 cvDestroyWindow ("示例"); 83 }
运行测试
1. 将格式为 avi 的测试视频拷贝到 D 盘,命名为 "1.avi"。
2. 运行结果:
3. 可以看到该视频播放程序有了滚动条,且滚动条随着视频的播放而自动推进。