《学习OpenCV》第二章样例代码实现

前言

在学习OpenCV库的时候,发现了可能由于版本更新,导致的书上的代码无法实现的情况。特此把没一个例子的代码和完整的编译运行命令都记录下来。并记录要点,以备复习。


第二章

一,显示图像

  • 程序
  1. //用于从磁盘加载图片并在屏幕上显示的简单OpenCv程序
    #include"highgui.h"
    
    int main(int argc,char ** argv)
    {
        //将图像文件加载至内存
    	IplImage* img = cvLoadImage(argv[1] , 1);
        //创建窗口,指定标题,设置尺寸为匹配图像大小
    	cvNamedWindow("Example1",CV_WINDOW_AUTOSIZE);
        //在已有窗口中显示IplImage指针指向的图像
    	cvShowImage("Example1",img);
        //等待用户按键,暂停程序
    	cvWaitKey(0);
        //释放内存
    	cvReleaseImage(&img);
        //销毁窗口
    	cvDestroyWindow("Example1");
    
    	return 0;
    }
  • 编译过程和运行
xbw@xbw-VirtualBox:~/code/cv_test$ gcc 1_test.c `pkg-config --cflags --libs opencv`
xbw@xbw-VirtualBox:~/code/cv_test$ ./a.out original.jpg 

  • 要点

函数cvLoadImage()书中仅有一个文件指针参数,实际上有两个。

函数原型:IplImage* cvLoadImage( const char* filename, int flags=CV_LOAD_IMAGE_COLOR );

指定的颜色可以将输入的图片转为3信道(CV_LOAD_IMAGE_COLOR), 单信道(CV_LOAD_IMAGE_GRAYSCALE), 或者保持不变(CV_LOAD_IMAGE_ANYCOLOR)。

cvLoadImage函数使用方法

  cvLoadImage( filename, -1 ); 默认读取图像的原通道数

  cvLoadImage( filename, 0 ); 强制转化读取图像为灰度图

  cvLoadImage( filename, 1 ); 读取彩色图

 

二,显示视频

  • 程序
  1. //循环读取视频的每一帧达到播放视频的效果
    #include"highgui.h"
    
    int main(int argc,char** argv)
    {
        //创建窗口
    	cvNamedWindow("Example2",CV_WINDOW_AUTOSIZE);
        //读取avi文件,创建CvCapture结构指针
    	CvCapture* capture = cvCreateFileCapture(argv[1]);
    	IplImage* frame;
    	while(1)
    	{
            //将下一帧视频文件载入内存
    		frame = cvQueryFrame(capture);
    		if(!frame) break;
    		cvShowImage("Example2",frame);
            //如果没有按ESC,延迟200ms
    		char c = cvWaitKey(200);
    		if(c == 27) break;
    	}
        //释放CvCapture内存
    	cvReleaseCapture(&capture);
    	cvDestroyWindow("Example2");
    
    	return 0;
    }
    
  • 编译过程和运行
xbw@xbw-VirtualBox:~/code/cv_test$ gcc 1_test.c `pkg-config --cflags --libs opencv`
xbw@xbw-VirtualBox:~/code/cv_test$ ./a.out tree.avi

  • 要点

并非实际的播放视频,可以通过延迟时间的方式来控制播放帧率,后面可以通过CvCapture结构体来确定准确帧率。

结构都是:创建窗口,读取文件,播放图片,释放内存,销毁窗口。一次完成,没什么问题。

三,添加视频进度条

  • 程序
  1. #include"highgui.h"
    #include"cv.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(int argc,char** argv)
    {
    	cvNamedWindow("Example3",CV_WINDOW_AUTOSIZE);
    	g_capture = cvCreateFileCapture(argv[1]);
        //获取视频总帧数
    	int frames = (int) cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT);
    	if(frames != 0)
    	{
            //创建滚动条:名称,所在窗体,全局变量指针,总帧数,回调函数。
    		cvCreateTrackbar(
    				"Position",
    				"Example3",
    				&g_slider_position,
    				frames,
    				onTrackbarSlide
    				);
    	}
    	IplImage* frame;
        //播放视频
    	while(1)
    	{
    		frame = cvQueryFrame(g_capture);
    		if(!frame) break;
    		cvShowImage("Example3",frame);
    		char c = cvWaitKey(200);
    		if(c == 27) break;
    	}
    	cvReleaseCapture(&g_capture);
    	cvDestroyWindow("Example3");
    
    	return 0;
    }
    
  • 编译过程和运行
xbw@xbw-VirtualBox:~/code/cv_test$ gcc 1_test.c `pkg-config --cflags --libs opencv`
xbw@xbw-VirtualBox:~/code/cv_test$ ./a.out tree.avi

  • 要点

案例只有生成进度条和回调的功能,没有实现进度条随帧数改变,读取的总帧数也有错误。实际只有几十帧,而显示了四百多帧。并不太了解怎么修改,等后面详细学习再看看吧。

应该有一个刷新滚动条位置的函数,试过给全局变量自增,但是没有效果。

四,简单图像处理

  • 程序
  1. #include"cv.h"
    #include"highgui.h"
    
    void example(IplImage* image)
    {
    	cvNamedWindow("Example4-in",CV_WINDOW_AUTOSIZE);
    	cvNamedWindow("Example4-out",CV_WINDOW_AUTOSIZE);
    	cvShowImage("Example4-in",image);
        //分配输出图片的内存空间
    	IplImage* out = cvCreateImage(
    			cvGetSize(image),
    			IPL_DEPTH_8U,
    			3
    			);
        //平滑函数
    	cvSmooth(image,out,CV_GAUSSIAN,3,3,0,0);
    	cvShowImage("Example4-out",out);
    	cvReleaseImage(&out);
    	cvWaitKey(0);
    	cvDestroyWindow("Example4-in");
    	cvDestroyWindow("Example4-out");
    }
    
    int main(int argc,char** argv)
    {
    	IplImage* img = cvLoadImage(argv[1],1);
    	example(img);
    
    	return 0;
    }
    
  • 编译过程和运行
xbw@xbw-VirtualBox:~/code/cv_test$ gcc 1_test.c `pkg-config --cflags --libs opencv`
xbw@xbw-VirtualBox:~/code/cv_test$ ./a.out org.jpg

  • 要点

函数cvSmooth(image,out,CV_GAUSSIAN,3,3,0,0);在原书中只有5个参数,查阅头文件定义有7个。似乎opencv几个版本差异并不小,而且做不到向后兼容。

五,读取摄像头视频

  • 程序
  1. #include"highgui.h"
    //和读取视频没有区别,都通过CvCapture指针
    int main(int argc,char** argv)
    {
    	cvNamedWindow("Example2",CV_WINDOW_AUTOSIZE);
    	CvCapture* capture;
        //-1为随机选择一个相机录像
    	capture = cvCreateCameraCapture(-1);
    
    	IplImage* frame;
    	while(1)
    	{
    		frame = cvQueryFrame(capture);
    		if(!frame) break;
    		cvShowImage("Example2",frame);
    		char c = cvWaitKey(30);
    		if(c == 27) break;
    	}
    	cvReleaseCapture(&capture);
    	cvDestroyWindow("Example2");
    
    	return 0;
    }
  • 编译过程和运行
xbw@xbw-VirtualBox:~/code/cv_test$ gcc 1_test.c `pkg-config --cflags --libs opencv`
xbw@xbw-VirtualBox:~/code/cv_test$ ./a.out

  • 要点

在VirtualBox虚拟机下,最开始无法读取摄像头。原来以为是驱动问题,通过V4L2调取UVC摄像头,能读取到但无法读取流。后来证明是虚拟机的问题。需要下载VirtualBox Extension Pack,就是usb增强包,用USB3.0可以正常读取。


总结

第二章还有些练习,不过大体上都是对于highgui.h库的运用。运行完上述例子,大体的逻辑如下:

  1. 命名窗口
  2. 创建图像/视频指针
  3. 读取图像/视频帧,分配内存
  4. 在窗口中显示
  5. 等待按键操作
  6. 销毁窗口
  7. 释放图像/视频指针

值得一提的就是,没有我想象中那么复杂的摄像头驱动设置,V4L2驱动框架调用video0的UVC摄像头,很自然的就完成了。我觉得后续难点是图形学的相关知识,对于图像的通道什么的属性完全没了解到话,根本看不下去。很多问题的解决方法都是线性代数的术语,要重新补一补。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值