本文章使用的系统时Ubuntu 18.04 desktop
一、Ubuntu上安装opencv
安装及下载参考此链接,我就不详细说明
https://blog.csdn.net/qq_43279579/article/details/109231383
二、一个打开摄像头显示处理视频的程序
- 代码
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
VideoCapture capture(0);
while (1)
{
Mat frame;
capture >> frame;
imshow("读取视频帧", frame);
waitKey(30);
}
system("pause");
return 0;
}
- 编译
g++ test.cpp -o test `pkg-config --cflags --libs opencv`
注意:此处用的是反引号
- 运行
程序出现无法打开摄像头
解决方法:
①查看摄像头标志是否高亮
②如果摄像头不是高亮,就点击它,选择连接
第一次连接可能会连接失败或没有下面这个界面弹出,如果遇到这个情况按照以下操作进行
打开此电脑(Win10)->管理->服务和应用程序->VMware USB Arbitration,重启动此服务,回到虚拟机查看就会弹出上面的界面
③查看是否可以使用摄像头
lsusb 查看usb设备列表
ls /dev/video* 查看摄像头驱动安装
sudo apt-get install cheese 如果已经安装,这步可以省略
cheese 打开摄像头
如果使用cheese打开摄像头发现,摄像头能打开,但是画面却无法显示(黑屏),这个问题不解决,运行程序任然会出现问题,导致程序出现打开摄像头失败超时的问题
解决办法:
首先虚拟机上打开虚拟机(M)->设置,接着点击USB控制器,更换USB兼容性,原来是USB 2.0就更换为USB 3.0,若是USB 3.0就更换为USB 2.0。选择确定,虚拟机就重新启动,启动完成,就重新设置摄像头的连接,完成后,使用cheese看摄像头是否能够看到画面,能看到画面就表示完成了。
编译过程获得opencv头文件、链接lib库文件的路径的方法:
如果编译没有指定路径,头文件就会查看gcc的环境变量和查找系统默认的目录:/usr/include;/usr/local/include,链接lib库gcc的环境变量和查找默认路径/lib;/usr/lib;/usr/local/lib。
运行效果
4. 问题分析
①如果要求打开你硬盘上一个视频文件来播放,如何修改?
将代码中的VideoCapture capture(0);修改为VideoCapture capture("/home/ubuntu/video/test.mp4")
即将0改为需要播放的视频名称以及它所存放的路径
②在while循环中,Mat是一个什么数据结构? 为什么一定要加一句waitKey延时代码,删除它行不行?
Mat是一个矩阵,每个图像都是由无数的点构成的,即Mat是一个图像矩阵。
waitKey()函数的功能是不断刷新图像,如果没有这个就无法实现画面的实时显示,即看不到画面的变化。
③此代码会在while循环中一直运行,你如果试图用鼠标关闭图像显示窗口,会发现始终关不掉。需要用键盘Ctrl+C 强制中断程序,非常不友好。如何改进。
增加一个判断语句,来进行关闭
三、打开摄像头采集图像并保存(改进)
- 代码
/*********************************************************************
打开电脑摄像头,空格控制视频录制,ESC退出并保存视频RecordVideo.avi
*********************************************************************/
#include<iostream>
#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
void main()
{
//打开电脑摄像头
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "error" << endl;
waitKey(0);
return;
}
//获得cap的分辨率
int w = static_cast<int>(cap.get(CV_CAP_PROP_FRAME_WIDTH));
int h = static_cast<int>(cap.get(CV_CAP_PROP_FRAME_HEIGHT));
Size videoSize(w, h);
VideoWriter writer("RecordVideo.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25, videoSize);
Mat frame;
int key;//记录键盘按键
char startOrStop = 1;//0 开始录制视频; 1 结束录制视频
char flag = 0;//正在录制标志 0-不在录制; 1-正在录制
while (1)
{
cap >> frame;
key = waitKey(100);
if (key == 32)//按下空格开始录制、暂停录制 可以来回切换
{
startOrStop = 1 - startOrStop;
if (startOrStop == 0)
{
flag = 1;
}
}
if (key == 27)//按下ESC退出整个程序,保存视频文件到磁盘
{
break;
}
if (startOrStop == 0 && flag==1)
{
writer << frame;
cout << "recording" << endl;
}
else if (startOrStop == 1)
{
flag = 0;
cout << "end recording" << endl;
}
imshow("picture", frame);
}
cap.release();
writer.release();
destroyAllWindows();
}
- 编译
编译过程会出现图片中的报错,有这个错误也不要担心,只需要将代码中判断摄像头是否能够打开的语句删掉或者将这段语句中的return语句后面加上0就可以解决了。
//删掉这样段代码
if (!cap.isOpened())
{
cout << "error" << endl;
waitKey(0);
return;
}
//将上面的这段代码修改为下面的代码
if (!cap.isOpened())
{
cout << "error" << endl;
waitKey(0);
return 0;
}
- 运行
这个是视频采集画面的记录过程,当按下ESC按键时,视频采集画面就会关闭,采集记录过程也就结束了。(摄像头采集的画面就不展示了,就展示采集记录的过程)
四、小结
通过这个简单的摄像头采集的程序,基本能够掌握在Ubuntu下,该怎么使用opencv,怎么来完成这个过程。虽然,这个过程开始就遇到摄像头打不开的情况,但是,再查找资料后,也顺利的解决了。所以,遇到问题的小伙伴们,不要就此放弃,查找资料解决也是很快的。