嵌入式系统开发04——Ubuntu系统下OpenCV的安装与使用

每一个程序背后都站着一堆优秀的代码库。本文主要叙述通过学习opencv图像库编程,了解如何借助第三方库函数完成一个综合程序设计。

一、OpenCV简介

OpenCV 是一个基于 Apache2.0 许可(开源)发行的跨平台计算机视觉和机器学习软件库。

1、OpenCV的优势:

  • 跨平台:
    OpenCV 可以在不同的系统平台上使用,包括Windows,Linux,OS,X,Android和iOS

  • 编程语言:
    OpenCVC++ 语言编写,它具有 C ++,Python,JavaMATLAB 接口,如今也提供对于 C#、Ch、Ruby,GO 的支持。

  • 活跃的开发团队:
    自从第一个预览版本于2000年公开以来,目前已更新至 OpenCV4.5.3

  • 丰富的API:
    完善的传统计算机视觉算法,涵盖主流的机器学习算法,同时添加了对深度学习的支持。

  • 开源:
    BSD 许可证授权发行,可以在商业和研究领域中 免费使用

2、OpenCV的应用领域

增强现实 人脸识别 手势识别 人机交互 动作识别 运动跟踪 物体识别 图像分割 机器人

二、安装OpenCV

1、安装环境

本文的所有操作均在通过 VMware Workstation Pro 16.2.4 软件,在 Ubuntu18.04 Desktop 系统下进行操作,安装的是 C/C++ 图像处理开源软件库 OpenCV3.4.11

注意:若打开桌面版的Ubuntu时提醒 VMware Workstation 16 此平台不支持虚拟化的Intel VT-x/EPT. 不使用虚拟化的Intel VT-x/EPT,是否继续? 可以试试这篇 博客 里面的方法,并在设置关闭 “内核隔离”,笔者通过此方法已经解决了该问题。

2、安装

在Ubuntu中打开终端的快捷键是[Ctrl]+[Alt]+[T],这样我们就可以在命令行进行接下来的操作了。

(1)安装cmake

sudo apt-get install cmake

安装cmake

(2)依赖环境

sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev
sudo apt-get install libgtk2.0-dev
sudo apt-get install pkg-config

依赖环境

(3)下载OpenCV

下载地址:https://opencv.org/releases/
点击 Sources 进行下载自己需要的版本
opencv

(4)将压缩包解压并复制到Ubuntu的Home目录下

windows 下载压缩包,并解压,将解压后的文件复制到 Ubuntu 系统的 home 目录下

解压

(5)进入 OpenCV 文件并创建 build文件

键入[Ctrl]+[Alt]+[T],这样我们就可以在命令行进行接下来的操作了。
这里我的文件名为 opencv-3.4.11 ,使用 cd命令 将自己的操作路径改到 opencv-3.4.11

cd opencv-3.4.11

opencv-3.4.11 文件夹下新建 build 文件夹,并将操作路径改到build

mkdir build
cd build

build

(6) cmake

输入如下命令,使用 cmake 编译参数::

sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..

cmake

(7)使用 make 创建编译

这一步仍然是在 build 文件夹下进行。

sudo make -j4

可以使用sudo make -j8sudo make -j4sudo make
注:单线程编译:sudo make ,这会等待比较长的时间,如果你想更快编译完,可以使用命令:sudo make -j4sudo make -j8 ,而 -j4 表示使用 4 个线程进行编译,而 -j8 表示使用 8 个线程进行编译。

我这里使用 -j4 是因为使用 -j8 失败了,但是没有弄清楚为什么会失败

编译

这里会等待大概十几分钟,报错的话可以多尝试几次

(8)进行安装

sudo make install

安装

(9)完成配置

1.用 gedit 打开 /etc/ld.so.conf
2.在文件中加上一行 include /usr/loacal/lib
其中 /usr/loacal/libOpenCV 安装路径也就是 makefile 中指定的安装路径

sudo gedit /etc/ld.so.conf

配置1

3.修改完成后点击右上角的 save
报错
保存后会看到之前的警告信息,不用担心,这是正常情况。键入Ctrl+C 来继续下面的操作。

4.更新系统共享链接库:

sudo ldconfig

5.配置 bash ,修改 bash.bashrc 文件:

sudo gedit /etc/bash.bashrc 

在文件末尾加入:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
配置bash

6.保存并退出,然后执行如下命令使得配置生效:

source /etc/bash.bashrc

7.更新一下:

sudo updatedb

更新配置

(10)检查

接下来查看 OpenCV 的版本信息是否匹配:

pkg-config --modversion opencv

版本信息

至此,OpenCV 的安装终于完成了。

三、通过OpenCV进行图片特效展示

1、目标

1) 编写一个打开图片进行特效显示的代码 test1.cpp;

2)解释 gcc test1.cpp -o test1 `pkg-config --cflags --libs opencv` 这条编译命令,它是如何获得opencv头文件、链接lib库文件的路径的?

3)改用make+makefile方式编译上述程序(用变量命名格式写makefile文件,并包括 clean选项)

2、创建文件

创建一个文件夹存放代码文件:

mkdir test1
cd test1

创建一个 test1.cpp 文件。

vim test1.cpp

00

3、通过vim编写test1.cpp

#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
	CvPoint center;
    double scale = -3; 

	IplImage* image = cvLoadImage("test1.jpg");
	argc == 2? cvLoadImage(argv[1]) : 0;
	
	cvShowImage("Image", image);
	
	
	if (!image) return -1; 	center = cvPoint(image->width / 2, image->height / 2);
	for (int i = 0;i<image->height;i++)
		for (int j = 0;j<image->width;j++) {
			double dx = (double)(j - center.x) / center.x;
			double dy = (double)(i - center.y) / center.y;
			double weight = exp((dx*dx + dy*dy)*scale);
			uchar* ptr = &CV_IMAGE_ELEM(image, uchar, i, j * 3);
			ptr[0] = cvRound(ptr[0] * weight);
			ptr[1] = cvRound(ptr[1] * weight);
			ptr[2] = cvRound(ptr[2] * weight);
		}

	Mat src;Mat dst;
	src = cvarrToMat(image);
	cv::imwrite("test.png", src);

    cvNamedWindow("test",1);  	imshow("test", src);
	 cvWaitKey();
	 return 0;
}

4、编译

编译分两种情况:

c++文件编译命令:

g++ test1.cpp -o test1 `pkg-config --cflags --libs opencv`

c文件编译命令:

gcc test1.cpp -o test1 `pkg-config --cflags --libs opencv`

通过 ll命令 查看,发现生成了可执行文件 test1
编译

5、运行test1

  • 首先,在test1文件夹里面存放一张照片,一定要和 .cpp 文件放在同一个文件夹里面,不然程序不能运行。
    图片位置
    名字和格式都要和代码中保持一致,代码中文件名如下保持一致。
    test1
  • 接着输入下面的命令运行该程序
./ test1
  • 运行效果展示:
    在test1文件夹中生成一张将原图 test1.jpg 四周变黑的照片 test.png
    png
    原图效果:
    原图
    处理后的效果:
    处理后

6、优化

虽然上面的操作可以实现图片进行特效显示,但是会提醒 Failed to load module “canberra-gtk-module”
报错
我们只需要重新安装一下 canberra-gtk-module

sudo apt-get install libcanberra-gtk-module

更新
安装完成后,重新启动虚拟机,再执行 test1 就不会报错了
不报错

7、gcc编译命令解析

gcc test1.cpp -o test1 `pkg-config --cflags --libs opencv`
命令格式:

gcc编译器:gcc/g++ + 文件名 + -o + 输出文件流名称 + `支持包`

命令解析:

这个编译命令中用到了 pkg-config 工具,它主要有以下几个功能:

  • 1.检查库的版本号。如果所需要的库的版本不满足要求,它会打印出错误信息,避免链接错误版本的库文件。
  • 2.获得编译预处理参数,如宏定义,头文件的位置。
  • 3.获得链接参数,如库及依赖的其它库的位置,文件名及其它一些连接参数。
  • 4.自动加入所依赖的其它库的设置

使用 pkg-config 时,选项 - -cflags 它是用来指定程序在编译时所需要头文件所在的目录,选项 - -libs 则是指定程序在链接时所需要的动态链接库的目录。

gcc 编译命令: gcc test1.cpp -o test1 `pkg-config --cflags --libs opencv` 这条编译命令,就是通过上述方式获得 opencv 头文件、以及链接lib库文件的路径的。

8、用make+makefile方式编译上述程序

  • 首先我们将上面操作产生的 test1 可执行文件和处理后的图片 test.png 删除
    删除
    gcc test1.cpp -o test1 pkg-config --cflags --libs opencv
  • 然后,在 test1 文件夹创一个 makefile 文件,并且通过变量命名格式写 makefile 文件,makefile 文件内容如下:
vim makefile
.PHONY: clean

CC  = g++
BIN = a.out
OBJS = test1.o
TCPP = test1.cpp
T = test1
OPCV = `pkg-config --cflags --libs opencv`

$(T): $(TCPP) 
        $(CC) $(TCPP) -o $(T) $(OPCV)
$(BIN): $(OBJS)
        $(CC) -o $(BIN) $(OBJS)
$(OBJS): $(TCPP)
        $(CC) -c -o $(OBJS) $(TCPP)
        
clean:
        rm -f $(BIN) $(OBJS)

注意:每一句recipe(就是要执行的shell命令)的开头,都必须有一个tab。 而makefile中的其他东西,例如 target: prerequisite、ifeq 、变量赋值等等,前面一般不能有tab

make
  • 此时输入make命令,并键入 ./test1,发现能够实现特效展示,并且在test1 文件夹下生成了 test1可执行文件和test.png。
    makefile
    61
    于是,通过meke+makefile实现了该程序的编译工作。

四、通过opencv打开摄像头压缩视频

1、目标

(1)练习使用opencv库编写打开摄像头压缩视频的程序。参考示例代码1和示例代码2。
(2)回答:
a.如果要求打开你硬盘上一个视频文件来播放,请问示例代码1第7行代码如何修改?
b.在示例代码1第9行的while循环中,Mat是一个什么数据结构? 为什么一定要加一句waitKey延时代码,删除它行不行?
c.示例代码1代码会在while循环中一直运行,你如果试图用鼠标关闭图像显示窗口,会发现始终关不掉。需要用键盘Ctrl+C 强制中断程序,非常不友好。如何改进?

2、播放视频

  • 创建一个 test2.cpp 文件。
mkdir test2
cd test2
vim test2.cpp
  • 通过vim文本编辑器编写 test2.cpp
//改进前的代码
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
	VideoCapture capture(0);
	while(1)
	{
		Mat frame;
		capture >> frame;
		imshow("读取视频帧",frame);
		waitKey(30);
	}
	system("pause");
	return 0;
}
//改进后的代码
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
	//从文件中读取视频
	VideoCapture capture("111.mp4");
	//循环显示每一帧
	while(1){
		Mat frame;//定义一个Mat变量,用于存储每一帧的图像
		capture >> frame;//读取当前帧
		if(frame.empty())//播放完毕,退出
			break;
		imshow("读取视频帧",frame);//显示当前帧
		waitKey(30);//掩饰30ms
	}
	system("pause");
	return 0;
}
  • 代码说明(解决目标中的遗留问题):

  • a.如果要求打开你硬盘上一个视频文件来播放,请问示例代码1第7行代码如何修改?
    第七行语句:VideoCapture capture(0),后面的参数设置为 0 ,则从摄像头读取视频并循环显示每一帧;如果设置为一个视频的文件名,比如:111.mp4 ,则会将视频读取并循环显示每一帧。

  • b.在示例代码1第9行的while循环中,Mat是一个什么数据结构? 为什么一定要加一句waitKey延时代码,删除它行不行?
    while 循环体中的 Mat 数据结构其实是一个点阵,对应图像上的每一个点,点的集合形成了一帧图像,有关 Mat 详解请看:OpenCV中Mat数据结构
    waitKey(30) ,中的参数单位是 ms 毫秒,也就是每一帧间隔 30 ms ,该语句时不能删除的,否则会执行错误,无法播放视频或录制视频。

  • c.示例代码1代码会在while循环中一直运行,你如果试图用鼠标关闭图像显示窗口,会发现始终关不掉。需要用键盘Ctrl+C 强制中断程序,非常不友好。如何改进?

原代码会在while循环中一直运行,如果试图用鼠标关闭图像显示窗口,会发现始终关不掉。需要用键盘 Ctrl+C 强制中断程序,本文中的 test2.cpp 已经经过修改,当视频播放完后,会自动结束播放

10

  • test2 目录下放一个 111.mp4 视频文件,用来查看代码运行效果。
    11
  • 编译 test2.cpp 文件,生成可执行文件。
g++ test2.cpp -o test2 `pkg-config --cflags --libs opencv`

15
在这里插入图片描述

  • 键入 ./test2 运行可执行文件,发现可以播放视频 111.mp4
    666

由于本人的电脑没有摄像头,所以接下来这一部分借用同学的电脑来完成。

3、虚拟机获取摄像头权限

  • 使用快捷键 Win+R ,输入 services.msc ,点击“确定”
    0

  • 找到 VMware USB Arbitration S…服务,确保启动了。
    1

  • 在VMware 中点击 “ 虚拟机 ” ,然后点击 “ 设置(S)… ”。
    2

  • 选择 “ USB控制器 ” ,将 “ USB兼容性 ” 设置为 “ USB 3.1” ,并点击确定。
    3.1

  • 选择 “ 虚拟机 ” ,再选择 “ 可移动设备 ” ,再选择 “ Acer Integrated Camera ” ,最后点击 “ 连接 ” ,再弹出的窗口内点击 “ 确定 ” 。
    连接

  • 虚拟机右下角这个摄像头图标有个小绿点,则连接成功。
    摄像头

4、调用摄像头录制视频

由于本人的电脑没有摄像头,所以接下来这一部分借用同学的电脑来完成。

  • 首先输入以下命令来新建文件 test3 ,改变当前的操作路径,并且通过vim文本编辑器编写 test3.cpp 调用摄像头录制视频。
mkdir test3
cd test3
vim test3.cpp

创建

  • 在test3.cpp中写入如下代码:
/*********************************************************************
打开电脑摄像头,空格控制视频录制,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;

int main()
{
	//打开电脑摄像头
	VideoCapture cap(0);
	if (!cap.isOpened())
	{
		cout << "error" << endl;
		waitKey(0);
		return 0;
	}

	//获得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;
}
  • 编译 test3.cpp
g++ test3.cpp -o test3 `pkg-config --cflags --libs opencv`

通过 ll命令 查看,发现生成了 test3 可执行文件。
ll

  • 运行 test3 调用摄像头录制视频
./test3

000

Esc 退出录制并保存 .avi 文件:
451
到此就成功实现了调用摄像头录制视频的目的。

总结:

通过学习opencv图像库编程,我了解如何借助第三方库函数完成一个综合程序设计,也实现了桌面版Ubuntu的初步探索,加深了我对makefile的理解。但是也让我认识到了自己对Ubuntu的理解和认识仍然停留在初级水平,还远远不能独立实现在ubuntu系统下的综合程序设计,还需要不断地学习来提升自己的水平和能力。本次实验中需要用到摄像头,但是由于我的电脑上没有摄像头,我尝试了多种方法来通过USB连接来调用手机上面的摄像头,但是在Ubuntu系统下未能实现,在Windows系统下可以通过DroidCam来实现。


参考列表:
1.OpenCV
2. OpenCV简介
3. VMware Workstation 16 在此主机上不支持嵌套虚拟化 修复方法
4. ubuntu安装opencv的正确方法
5.Ubuntu18.04下OpenCV3.4.11的安装及使用示例
6.Ubuntu18.04使用opencv库编写打开摄像头压缩视频

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

6¿6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值