opencv+ffmpeg环境(ubuntu)搭建全面详解

news2024/9/30 11:38:32

一.先讲讲opencv和ffmpeg之间的关系

1.1它们之间的联系

我们知道opencv主要是用来做图像处理的,但也包含视频解码的功能,而在视频解码部分的功能opencv是使用了ffmpeg。所以它们都是可以处理图像和视频的编解码,我个人感觉两个的侧重点不一样。

1.2它们之间的区别

这就要提上面我所说的它们的侧重点是不一样。

OpenCV专注处理图像,以及图像相关的处理应用,不严谨地可以认为是PhotoShop。Opencv主要做一些识别 跟踪机器视觉应用。

FFmpeg专注处理视频、音频的编解码、转换等,不严谨地可以认为是格式工厂和PotPlayer的结合体。主要应用是编解码,各种格式转换。

二.opencv和ffmpeg版本匹配

在搭建环境之前,我着重强调下两者版本匹配的问题,因为在我本人搭建环境的时候由于版本不匹配问题踩了太多的坑,怕了。所以一开始把这些干扰因素处理好,后面可以省很多事。

2.1如果版本不匹配可能会出哪些问题呢?

会在编译opencv的时候出现各种识别不到某些定义的错误,导致编译不过。

具体有:

2.1.1问题一

error: ‘CODEC_ID_H264’ was not declared in this scope

{ CODEC_ID_H264, MKTAG('H', '2', '6', '4') }

网友给的就解决方法是,编译的时候不开启ffmpeg的编译:

-D WITH_FFMPEG=OFF 

我试过,可以编译通过,但同时也如同自断一臂,给使用ffmpeg功能(视频处理类)带来巨大麻烦,或者干脆是用不了。因此我认为,最好的办法还是,版本匹配,完美编译,完美使用,这才用的安心,根本之道。

2.1.2问题二

error: 'CODEC_FLAG_GLOBAL_HEADER' was not declared in this scope

这种解决办法是,补充添加未定义的宏,这个如果你了解不深刻里面的原理机制,一般人想不到,也只有是大佬才能理解并找到的方法。

总之基本上出问题的都是ffmpeg和opencv版本匹配问题,为啥我们不一开始就做好呢,是吧。

2.2如何知道ffmpeg和opencv的匹配的版本

为了解决这个问题,本人也是走了一大圈,才整清楚,可能最终说起来也就几句话的事,但过程是非常曲折的,不过正是经历了这种过程,才更加深刻吧,也同时也锻炼了下自己的耐心,加强了一点专研的精神,也不错哈!下面进入主题!

根据网友提供的方法进入opencv源码目录

按理说这里面应该会有一个叫ffmpeg_version.cmake的文件,里面会列出opencv相对应的ffmpeg版本号,类似下图:

那些带数字的就是某个版本的ffmpeg下,各个组件对应的版本,我们到ffmpeg官网去FFmpeg下载对应的版本源码即可。

上图只是为了说明问题,并没有去专门匹配版本号哈。

现在问题是,我的文件下没有ffmpeg_version.cmake啊,当时也是一脸懵。没办法,我就打开ffmpeg.cmake看看,是否能发现什么线索。

看到里面的内容,有几条线索,图片上已经标注出来了,这里总结下:

1.可以看到opencv需要的ffmpeg版本号对应的tag标签,以及commit id号;

2.ffmpeg.cmake其实是从上述网址***raw.git***上下载下来的;

为什么我的电脑上没有下载下来,一波查询,发现是访问不了该网址,网友也支招,在host文件加入ip什么的。我的办法是用github.com替代,其实是一样的。

进入另外的链接:

GitHub - opencv/opencv_3rdparty: OpenCV - 3rdparty

点击进去

你会发现opencv的commit id也匹配上了。

这样就找到了。关于版本匹配就讲这么多,当了解了整个过程是不是简单许多了,但如果不是自己一步一步摸索出来的,你是体会不到那种,遇到问题的焦躁以及解决完问题豁然开朗的感觉。

接下来就是分别下载ffmpeg和opencv的源码了,ffmpeg官网链接上面提供了,Releases - OpenCV是opencv的源码下载链接,自己选好版本,切记它们之间的版本匹配,要不我上面唠叨那么多是为了啥,然后编译安装,咱们继续往下走。

三.ffmpeg的安装流程

安装流程

这里建议先安装ffpmeg再安装opencv,因为安装opencv会用到ffmpeg。

先解压ffmpeg源码,然后进入到源码目录,输入如下指令:

这里说下,输入指令前先对支持库的安装

sudo apt-get install -y autoconf automake build-essential git libass-dev libfreetype6-dev libsdl2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev

再是参数配置指令输入

./configure --disable-x86asm --enable-shared --prefix=/usr/local/ffmpeg

参数含义是把ffmpeg安装到/usr/local/ffmpeg目录下,完了之后再输入

make
中间编译的时间会有点长,依电脑的性能而定
sudo make install

所有走完之后,会在/usr/local目录下看到ffmpeg文件夹,如下:

ffmpeg的工具和动态库都在里面了,为了编译时能找到ffmpeg的动态库,还要做如下处理:

创建文件ffmpeg.conf
sudo vi /etc/ld.so.conf.d/ffmpeg.conf
输入如下内容(ffmpeg动态库的路径)
/usr/local/ffmpeg/lib
最后使能生效
sudo ldconfig

看到下面内容说明安装成功

可以测试使用ffplayg工具播放一段视频

/usr/local/ffmpeg/bin/ffplay   **/**/***.mp4 (视频文件目录)

当然我们可以将ffmpeg的bin添加到全局变量,这样可以随时调用,不用加上绝对地址,编辑 profile 文件(sudo vi /etc/profile)在文件末尾添加:

export FFMPEG_HOME=/usr/local/ffmpeg 
export PATH=$FFMPEG_HOME/bin:$PATH

ffmpeg的安装到此结束,接下来是opencv的安装,继续往下走!

四.opencv的安装流程

安装流程

同样,将opencv的压缩包解压,进入源码目录,创建一个pc_build(如果以后要使用交叉编译,就换一个arm_build,扯远了)文件夹:

这里我是使用cmake图形化编译的,先安装一个cmake工具:

sudo apt-get install cmake cmake-qt-gui cmake-curses-gui

然后在pc_build目录下执行

cmake-gui

出现界面

这里仅演示ubuntu环境,不说交叉编译的

点击finish,然后再点击configure,配置一些参数,如下图

出现下图框出的版本信息,说明识别到了ffmpeg,如果没识别到怎么办呢?留个悬念后面讲。

最后点击generate。

小提示:

cmake过程中如果遇到卡住的情况,缺少文件需要下载,却一直下载不下来的情况

如:opencv源码安装文件下载问题:ippicv_2017u3_lnx, face_landmark_model.dat, tiny-dnn

配置:打开${opencv_folder}/3rdparty/ippicv/ippicv.cmake,
第47行  "https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_COMMIT}/ippicv/",
改成:"file://${path}",比如我的就是"file:///home/downloads/"

下载地址:https://github.com/opencv/opencv_3rdparty/tree/ippicv/

按照自己缺少的版本下载,下载慢的话可以把链接拷贝到迅雷里面下载。

开始编译

回到命令界面,先不要急着输入 make。首先在源码目录 3rdparty/protobuf/src/google/protobuf/stubs/common.cc 这个文件下第 33 行添加#define HAVE_PTHREAD 宏定义才可以编译的过。具体原因是 HAVE_PTHREAD 宏定义了 pthread 库。

cd ..
// 返回 opencv 源码顶层目录
vi 3rdparty/protobuf/src/google/protobuf/stubs/common.cc

再进入pc_build目录输入指令

make -j 16
漫长的等待编译编译完之后,安装
sudo make install

所有成功之后会在/usr/local目录下生成相应的文件

里面包含头文件和动态库

同样为了找到opencv的动态库做如下处理

创建文件opencv.conf
sudo vi /etc/ld.so.conf.d/opencv.conf
输入如下内容(ffmpeg动态库的路径)
/usr/local/lib
最后使能生效
sudo ldconfig

到此opencv编译安装完成!

前面挖的坑

前面提到一个坑,是在cmake的时候没有出现ffmpeg的版本怎么办,我的做法是先编译,不管,编译通过之后,将ffmpeg的pkgconfig里面的所有pc文件复到/usr/local/lib/pkgconfig里面,这文件里面是opencv的pc文件。

sudo cp /usr/local/ffmpeg/lib/pkgconfig/*.pc   /usr/local/lib/pkgconfig

然后按上面的操作在重新编译一次opencv,是不是有点崩溃,没办法。

当然我也想了一些操作,有网友说安装完ffmpeg后做如下操作,再去编译opencv

sudo vi /etc/profile
添加
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/ffmpeg/lib/pkgconfig
让环境变量生效
source /etc/profile

我这么处理了,貌似没用,也不知道怎么回事,有知道的网友,还请麻烦留言告知下。

到这里ffmpeg和opencv都安装好了,是不是按捺不住内心的激动,跃跃欲试。接下来走几个小栗子,磨磨刀,哈哈哈。

五.实践操作

是骡子是马拉出来溜溜,前面做了这么多就是为了学习和实践操作,接下来就写几个小程序跑一跑功能。

5.1显示一张图片

#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc,char** argv)
{
    Mat image = imread("11.png", 1 );//加载
    cv::namedWindow("picture",CV_WINDOW_AUTOSIZE);
    cv::imshow("picture", image);//显示图片
    waitKey(5000);//等待
    return 0;
}

5.2播放一段视频

#include<opencv2/opencv.hpp>
using namespace cv;

int main()
{
	//从摄像头读取视频
	VideoCapture capture("video.mp4");
	//循环显示每一帧
	while (1)
	{
		Mat frame;//定义一个Mat变量,用于存储每一帧的图像
		capture >> frame;//读取当前帧
		imshow("读取视频帧", frame);//显示当前帧
		waitKey(30);//延时30ms
	}

	system("pause");
	return 0;
}

5.3使用笔记本内置的摄像头,拍摄一段视频并保存

#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc,char** argv)
{
//打开电脑摄像头
    VideoCapture capture(0);
      if(!capture.isOpened()){
          cout<<"error"<<endl;
          waitKey(0);
          return 0;
      }
      //获得分辨率
      int w = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_WIDTH));
      int h = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_HEIGHT));
      cout<<"w="<<w<<endl;
      cout<<"h="<<h<<endl;
    
      Size videoSize(w,h);
      VideoWriter writer;
      writer.open("video.mp4",CV_FOURCC('M','J','P','G'),25,videoSize);
      if(!writer.isOpened()){
          cout<<"fail"<<endl;
          return -1;
      }
    
      Mat frame;
      int key;
      char startorstop=1;
      char flag=0;
      while(1){
        capture >> frame;
        if(key == 32){//按下空格开始录制、暂停录制   可以来回切换
            startorstop = 1-startorstop;
            if(startorstop == 0){
                flag = 1;
            }
        }
        if(key == 27){//按下ESC退出整个程序,保存视频文件到磁盘
            cout << "exit" << endl;
            break;
        }
        if(startorstop == 0 && flag == 1){
            writer << frame;
            cout << "recording" << endl;
        }else if(startorstop == 1){
            flag = 0;
            cout << "end recording" << endl;
        }
        imshow("picture",frame);
        key=waitKey(100);
        cout<<"key="<<key<<endl;
      }
      capture.release();
      writer.release();
      destroyAllWindows();
      return 0;
}

编译脚本

g++ test.cpp -o test -L/usr/local/lib -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_videoio -lopencv_imgcodecs

好了,到这里就告一段落了,一路走下来感觉要踩的坑我绝大部分都踩了一遍,不容易啊!所以后面的路,尽情发挥你的创造力吧!

如存在有误之处,还请广大网友指正!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/807794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【博客684】Multi-regional高可用模式部署VictoriaMetrics

Multi-regional模式部署VictoriaMetrics 整体架构图 每个工作负载区域&#xff08;地球、火星、金星&#xff09;都有一个 vmagent&#xff0c;通过监控设置将数据发送到多个区域。监控设置&#xff08;地面控制 1,2&#xff09;包含 VictoriaMetrics 时间序列数据库 (TSDB) 集…

四姑娘山三日游

趁着小孩放暑假&#xff0c;从昆明回来之后&#xff0c;直接自驾到四姑娘山。 第一天 成都-四川省阿坝藏族羌族自治州小金县日隆镇(20230711) 大概9:30从成都市郫都区出发&#xff0c;路线如下&#xff1a;郫都—都江堰–映秀—耿达—卧龙—四姑娘山&#xff0c;中途翻过巴朗…

Notepad++工具通过正则表达式批量替换内容

1.每行末尾新增特定字符串 CtrlH弹出小窗口&#xff1b;查找目标输入$&#xff0c;替换为输入特定字符串&#xff1b;选中循环查找&#xff0c;查找模式选正则表达式&#xff1b;最后点击全部替换 2.每行行首新增特定字符串 CtrlH弹出小窗口&#xff1b;查找目标输入^&…

会议OA之我的会议(会议排座送审)

目录 前言&#xff1a; 2.我的会议&#xff1a; 2.1实现的特色功能&#xff1a; 2.2思路&#xff1a; 2.3功能实现&#xff1a; 我的会议页面&#xff1a;myMeeting.jsp myMeeting.js Dao方法 在mvc中配置info信息 Meeting InfoAction 2.4会议排座的思路&#xff1a; …

第四代SHARC® ADSP-21479KBCZ-2A、ADSP-21479BSWZ-2A、ADSP-21479KSWZ-2A高性能DSP(数字信号处理器)

第四代SHARC Processors 现在内置低功耗浮点DSP产品&#xff08;ADSP-21478和ADSP-21479&#xff09;&#xff0c;可提供改进的性能、基于硬件的滤波器加速器、面向音频与应用的外设以及能够支持单芯片解决方案的新型存储器配置。所有器件都彼此引脚兼容&#xff0c;而且与以往…

【Android知识笔记】UI体系(二)

什么是UI线程? 常说的UI线程到底是哪个线程?UI线程一定是主线程吗? 下面先给出两条确定的结论: UI线程就是刷新UI所在的线程UI是单线程刷新的关于第二条为什么UI只能是单线程刷新的呢?道理很简单,因为多线程访问的话需要加锁,太卡,所以一般系统的UI框架都是采用单线程…

《重构的时机和方法》,值得程序员仔细研读的一本书

现有代码结构及框架沿用的比较久&#xff0c;持续在其上新增功能&#xff0c;可维护性与可扩展性变得越来越差&#xff0c;随着需求不断增加&#xff0c;现有代码变得越来越臃肿复杂&#xff0c;变得很难维护&#xff0c;甚至出现较严重的性能瓶颈&#xff0c;一般这个时候我们…

Thymeleaf入门

Thymeleaf是前端开发模板&#xff0c;springboot默认支持。前端模板用法大多数是类似的jsp、thymeleaf、vue.js都有while\for\if\switch等使用&#xff0c;页面组件化等。 1.前端模板区别 jsp是前后端完全不分离的&#xff0c;jsp页面写一堆Java逻辑。 thymeleaf好处是html改…

域名解析优先级

浏览器访问过程解析 访问网址——>首先在本地电脑看看hosts里面是否有域名对应IP地址&#xff0c;如何有直接访问对应IP&#xff0c; 如果没有&#xff0c;则联网询问DNS服务器&#xff08;一般网卡那边都配置了DNS服务器IP&#xff09; linux hosts 路径&#xff1a; w…

苍穹外卖-day07

苍穹外卖-day07 本项目学自黑马程序员的《苍穹外卖》项目&#xff0c;是瑞吉外卖的Plus版本 功能更多&#xff0c;更加丰富。 结合资料&#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频&#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…

中国气象局:到2030年,人工智能在气象应用领域取得世界领先地位

最近&#xff0c;中国气象局发布了《2023-2030年人工智能气象应用工作方案》&#xff0c;旨在加快推进国内人工智能气象应用技术体系建设&#xff0c;提升基础支撑能力&#xff0c;构建健全的人工智能气象应用政策环境&#xff0c;促进人工智能技术在气象观测、预报和服务领域的…

华为H12-821更新了32题,大家注意了

&#xff08;多选题&#xff09;使用堆叠和集群技术构建园区网的优势包括以下哪些项&#xff1f; A、业务中断时间大大减少 B、简化网络管理&#xff0c;降低网络部署规划的复杂度 C、可有效减少网络功耗 D、提高网络设备和链路的利用率 正确答案是…

教雅川学缠论02-K线

传统行情上的K线是下图中这样子的 而在缠论中K线是下面这样子的&#xff0c;它没有上影线和下影线 下图是武汉控股2023年7月的日K线 接下来我们将它转换成缠论K线&#xff08;画图累死我了&#xff09; K线理解了我们才能进行下一步&#xff0c;目前位置应该很好理解的

C++笔记之vector的resize()和clear()用法

C笔记之vector的resize()和clear()用法 code review! 文章目录 C笔记之vector的resize()和clear()用法1.resize()2.clear() 1.resize() 运行 2.clear() 运行

Python自动计算Excel数据指定范围内的区间最大值

本文介绍基于Python语言&#xff0c;基于Excel表格文件内某一列的数据&#xff0c;计算这一列数据在每一个指定数量的行的范围内&#xff08;例如每一个4行的范围内&#xff09;的区间最大值的方法。 已知我们现有一个.csv格式的Excel表格文件&#xff0c;其中有一列数据&#…

设计模式行为型——责任链模式

目录 什么是责任链模式 责任链模式的实现 责任链模式角色 责任链模式类图 责任链模式举例 责任链模式代码实现 责任链模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是责任链模式 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;又叫职…

【面试题】前端中 JS 发起的请求可以暂停吗?

这个问题非常有意思&#xff0c;我一看到就想了很多可以回复的答案&#xff0c;但是评论区太窄&#xff0c;就直接开一篇文章来写了。 审题 JS 发起的请求可以暂停吗&#xff1f;这一句话当中有两个概念需要明确&#xff0c;一是什么样的状态才能称之为 暂停&#xff1f;二是…

Appium+python自动化(三十五)- 命令启动appium之 appium服务命令行参数(超详解)

简介 前边介绍的都是通过按钮点击启动按钮来启动appium服务&#xff0c;有的小伙伴或者童鞋们乍一听可能不信&#xff0c;或者会问如何通过命令行启动appium服务呢&#xff1f;且听一一道来。 一睹为快 其实相当的简单&#xff0c;不看不知道&#xff0c;一看吓一跳&#xf…

TCP 三次握手四次挥手浅析

大家都知道传输层中的TCP协议是面向连接的&#xff0c;提供可靠的连接服务&#xff0c;其中最出名的就是三次握手和四次挥手。 一、三次握手 三次握手的交互过程如下 喜欢钻牛角尖的我在学习三次握手的时候就想到了几个问题&#xff1a;为什么三次握手是三次&#xff1f;不是…

shell脚本:使用mysqldump实现分库分表备份

一.什么是分库分表备份 分库分表备份是一种数据库备份策略&#xff0c;用于处理大型数据库系统中的数据分布和备份需求。当数据库的数据量非常大时&#xff0c;单个数据库可能无法满足性能和可扩展性的要求。为了解决这个问题&#xff0c;使用分库分表技术将数据库拆分成多个库…