opencv+ffmpeg环境(ubuntu)搭建全面详解
一.先讲讲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
好了,到这里就告一段落了,一路走下来感觉要踩的坑我绝大部分都踩了一遍,不容易啊!所以后面的路,尽情发挥你的创造力吧!
如存在有误之处,还请广大网友指正!
相关文章:

opencv+ffmpeg环境(ubuntu)搭建全面详解
一.先讲讲opencv和ffmpeg之间的关系 1.1它们之间的联系 我们知道opencv主要是用来做图像处理的,但也包含视频解码的功能,而在视频解码部分的功能opencv是使用了ffmpeg。所以它们都是可以处理图像和视频的编解码,我个人感觉两个的侧重点不一…...
开发基于 LoRaWAN 的设备须知--最大兼容性
最大兼容性配置简介 LoRaWAN开放协议的建立前提是每个制造的设备都可以被唯一且安全地识别。配置是创建唯一标识和相应秘密的过程。虽然配置过程是常规的,但存在一些可能并不明显的陷阱。本章尝试描述配置基于 LoRa 的设备的一些最佳实践。 配置概念 基于 LoRa 的设备配置与银…...
一、SpringBoot基础[日志]
一、日志 解释:SpringBoot使用logback作为默认的日志框架,其中还可以导入log4j2等优秀的日志框架 1.修改日志内容 修改整个日志格式:logging.pattern.console%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{15} 你好 %msg%n %d{yyy…...
libuv库学习笔记-networking
Networking 在 libuv 中,网络编程与直接使用 BSD socket 区别不大,有些地方还更简单,概念保持不变的同时,libuv 上所有接口都是非阻塞的。它还提供了很多工具函数,抽象了恼人、啰嗦的底层任务,如使用 BSD …...

C++多线程编程(第三章 案例1,使用互斥锁+ list模拟线程通信)
主线程和子线程进行list通信,要用到互斥锁,避免同时操作 1、封装线程基类XThread控制线程启动和停止; 2、模拟消息服务器线程,接收字符串消息,并模拟处理; 3、通过Unique_lock和mutex互斥方位list 消息队列…...

IOS UICollectionView 设置cell大小不生效问题
代码设置flowLayout.itemSize 单元格并没有改变布局大小, 解决办法如下图:把View flow layout 的estimate size 设置为None,上面设置的itemSize 生效了。...

浅谈3D隐式表示(SDF,Occupancy field,NeRF)
本篇文章介绍了符号距离函数Signed Distance Funciton(SDF),占用场Occupancy Field,神经辐射场Neural Radiance Field(NeRF)的概念、联系与区别。 显式表示与隐式表示 三维空间的表示形式可以分为显式和隐式。 比较常用的显式表…...

软件测试技能大赛任务二单元测试试题
任务二 单元测试 执行代码测试 本部分按照要求,执行单元测试,编写java应用程序,按照要求的覆盖方法设计测试数据,使用JUnit框架编写测试类对程序代码进行测试,对测试执行结果进行截图,将相关代码和相关截…...

MybatisPlus拓展篇
文章目录 逻辑删除通用枚举字段类型处理器自动填充功能防全表更新与删除插件MybatisX快速开发插件插件安装逆向工程常见需求代码生成 乐观锁问题引入乐观锁的使用效果测试 代码生成器执行SQL分析打印多数据源 逻辑删除 逻辑删除的操作就是增加一个字段表示这个数据的状态&…...
设置k8s中节点node的ROLES值,K8S集群怎么修改node1的集群ROLES
设置k8s中节点node的ROLES值 1.查看集群 [rootk8s-master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 54d v1.23.8 k8s-node1 Ready <none> 54d v1.…...

【*1900 图论】CF1328 E
Problem - E - Codeforces 题意: 思路: 注意到题目的性质:满足条件的路径个数是极少的,因为每个点离路径的距离<1 先考虑一条链,那么直接就选最深那个点作为端点即可 为什么,因为我们需要遍历所有点…...
微信开发者工具 miniprogram_npm 未找到
背景 微信开发者工具中,打开集成了vant-weapp的项目,构建npm时,报错\miniprogram_npm\ 未找到。 问题 微信开发者工具,工具----->构建npm时,提示 message:发生错误 Error: D:\some\path\miniprogram…...

计算机视觉(三)未有深度学习之前
文章目录 图像分割基于阈值、基于边缘基于区域、基于图论 人脸检测Haar-like特征级联分类器 行人检测HOGSVMDPM 图像分割 把图像划分成若干互不相交的区域。经典的数字图像分割算法一般是基于灰度值的两个基本特征之一:不连续性和相似性。 基于阈值、基于边缘 基于…...
二十六、媒体查询2
目录: 媒体查询介绍网页常用分界点 一、媒体查询介绍 媒体特性: width 视口的宽度 height 视口的高度 一般设计的时候,高度不考虑,只考虑宽度 //当视口的宽度是500像素的时候,变颜色media (width: 500px) {body{background-colo…...

Themis 国库建设计划启动,开启去中心化新征程
在未来的金融领域,去中心化金融(DeFi)正在成为一种重要的趋势。在这股DeFi热潮中,作为Filecoin 生态下的一颗璀璨明珠,Themis 上线仅2个月,多项数据便稳居Filecoin-FVM榜首,TVL更是牢牢处于File…...

uni-app:模态框的实现(弹窗实现)
效果图 代码 标签 <template><view><!-- 按钮用于触发模态框的显示 --><button click"showModal true">显示模态框</button><!-- 模态框组件 --><view class"modal" v-if"showModal"><view cla…...

第九章:stack类
系列文章目录 文章目录 系列文章目录前言stack的介绍stack的使用成员函数使用stack 总结 前言 stack是容器适配器,底层封装了STL容器。 stack的介绍 stack的文档介绍 stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除…...

FSM:Full Surround Monodepth from Multiple Cameras
参考代码:None 介绍 深度估计任务作为基础环境感知任务,在基础上构建的3D感知才能更加准确,并且泛化能力更强。单目的自监督深度估计已经有MonoDepth、ManyDepth这些经典深度估计模型了,而这篇文章是对多目自监督深度估计进行探…...

idea 安装 插件jrebel 报错LS client not configured.
这个报错找了好久,有博主说版本不对,我脑子没反应过来以为是随便换一个低版本的就行,没想到只能是2022.4.1 这个版本才行 一定要用jrebel 2022.4.1的插件版本!!!!! 插件下载地址&…...

Raki的读paper小记:RWKV: Reinventing RNNs for the Transformer Era
Abstract&Introduction&Related Work 研究任务 基础模型架构已有方法和相关工作 RNN,CNN,Transformer稀疏注意力(Beltagy等人,2020年;Kitaev等人,2020年;Guo等人,2022年&am…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...