在MacOS上Qt配置OpenCV并进行测试

目录

一.Qt环境准备

二.在Qt项目中加载Opencv库并编写代码测试 

1.使用Opencv加载图片

(1)在Qt中创建一个新项目

(2)在.pro文件中链接OpenCV库

(3)添加新资源文件

(4)在mainwindow.cpp中编写代码在窗口加载图片

 (5)代码中使用的OpenCV函数分析

        1)cv::imdecode()函数

        2)cv::namedWindow()函数

         3)cv::imshow()函数

        4)cv::waitKey()函数

        5)cv::destroyWindow()函数

2.使用Opencv加载视频

(1)使用Qt创建一个新项目

(2)在.pro文件中链接OpenCV库

(3)在mainwindow.cpp中编写代码

(4)代码中使用的OpenCV函数分析

        1)cv::VideoCapture

参考文档:


一.Qt环境准备

        上一篇博客我讲了如何下载配置OpenCV库,但是在Qt5.15.2使用OpenCV库时,出现了一个问题就是我下载的Qt5.15.2是x86架构的,不能对OpenCV库进行链接,而OpenCV库是arm架构的

        直接使用Qt5.15.2编译链接OpenCV库链接头文件是可以的,但是使用OpenCV代码就不能成功链接编译了

因此需要下载Qt6.3.1版本的, Qt6.3.1版本是arm架构的

下载完成后打开Qt  Creator在Qt版本里面加入Qt6.3.1的qmake

一般是在下载的Qt版本文件bin目录下

再在构建配套(Kit)中加入Qt6.3.1版本的构建配套

这样Qt环境就搭建好了

二.在Qt项目中加载Opencv库并编写代码测试 

1.使用Opencv加载图片

(1)在Qt中创建一个新项目

选择Qt6.3.1(arm)

(2)在.pro文件中链接OpenCV库

#链接OpenCV头文件
INCLUDEPATH +=/usr/local/include/
INCLUDEPATH +=/usr/local/include/opencv4/
INCLUDEPATH +=/usr/local/include/opencv4/opencv2
#链接OpenCV库文件
LIBS += -L/usr/local/lib -lopencv_gapi \-lopencv_stitching -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired \-lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm \-lopencv_highgui -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hfs \-lopencv_img_hash -lopencv_line_descriptor -lopencv_quality -lopencv_reg \-lopencv_rgbd -lopencv_saliency -lopencv_sfm -lopencv_stereo -lopencv_structured_light \-lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching \-lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot \-lopencv_videostab -lopencv_videoio -lopencv_xfeatures2d -lopencv_shape -lopencv_ml \-lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect \-lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto \-lopencv_photo -lopencv_imgproc -lopencv_core

(3)添加新资源文件

(4)在mainwindow.cpp中编写代码在窗口加载图片

#include "ui_mainwindow.h"
#include <opencv2/opencv.hpp>
#include <QDebug>
#include <QFile>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//以只读的方式打开图片文件QFile file(":/img/tree.jpg");if(!file.open(QFile::ReadOnly))  {qDebug() << "打开图片失败";}//将整个图片文件内容读取到一个 QByteArray 对象中QByteArray photo = file.readAll();cv::Mat img = cv::imdecode(std::vector<char>(photo.begin(), photo.end()), cv::IMREAD_COLOR);//判定图片是否加载成功if(img.empty()){qDebug() << "没有找到照片";}cv::namedWindow("tree", cv::WINDOW_AUTOSIZE);cv::imshow("tree", img);cv::waitKey(0); //cv::waitKey(10000);cv::destroyWindow("tree");
}MainWindow::~MainWindow()
{delete ui;
}

 运行结果:

 (5)代码中使用的OpenCV函数分析

        1)cv::imdecode()函数
//cv::Mat是OpenCV用于处理所有图像类型的结构
//cv::imdecode() 函数将 QByteArray 转换为 OpenCV 的图像格式 cv::Mat,以便进一步处理,cv::IMREAD_COLOR表示以彩色模式加载图像cv::Mat img = cv::imdecode(std::vector<char>(photo.begin(), photo.end()), cv::IMREAD_COLOR);

函数原型: 

Mat cv::imdecode (InputArray buf, int flags);
Mat cv::imdecode (InputArray buf, int flags, Mat *dst);
函数功能: 从内存的缓存区中读取图片
参数:    buf:一个数组或字节数组flags:用来指定图像加载的标志,通过这个参数,可以控制图像加载的一些行为和选项下面是falgs的枚举类型:enum cv::ImreadModes {cv::IMREAD_UNCHANGED = -1,            //按图像原样加载图像cv::IMREAD_GRAYSCALE = 0,             //以灰度模式加载图像cv::IMREAD_COLOR = 1,                 //以彩色模式加载图像cv::IMREAD_ANYDEPTH = 2,              //以原始深度加载图像cv::IMREAD_ANYCOLOR = 4,              //以任意颜色模式加载图像,返回一个3通道图像cv::IMREAD_LOAD_GDAL = 8,             //使用gdal驱动程序加载图像       cv::IMREAD_REDUCED_GRAYSCALE_2 = 16,  //将图像转换为单通道灰度图像,图像尺寸减小1/2cv::IMREAD_REDUCED_COLOR_2 = 17,      //图像转换为3通道BGR彩色图像,图像大小减少1/2cv::IMREAD_REDUCED_GRAYSCALE_4 = 32,  //将图像转换为单通道灰度图像,图像尺寸减小1/4cv::IMREAD_REDUCED_COLOR_4 = 33,      //将图像转换为3通道BGR彩色图像,图像大小减少1/4cv::IMREAD_REDUCED_GRAYSCALE_8 = 64,  //将图像转换为单通道灰度图像,图像尺寸减小1/8cv::IMREAD_REDUCED_COLOR_8 = 65,      //将图像转换为3通道BGR彩色图像,图像大小减少1/8cv::IMREAD_IGNORE_ORIENTATION = 128  //不根据EXIF的方向标志旋转图像(EXIF(Exchangeable Image File Format)是一种图像文件格式,用于存储数字图像中的元数据信息,例如相机设置、拍摄日期和时间、地理位置等。)}dst(可选):用于接收解码后的图像数据
返回值:成功: 一个Mat类型的值失败: NULL

例子: 

cv::Mat image;  // 定义用于存储解码后图像的 cv::Mat 对象
cv::imdecode(buffer, flags, &image);

         通过传递 &imagecv::imdecode() 函数的 dst 参数,解码后的图像数据将直接存储在 image

        也可以不使用第三个参数,直接使用返回值

cv::Mat image;  // 定义用于存储解码后图像的 cv::Mat 对象
image = cv::imdecode(buffer, flags);
        2)cv::namedWindow()函数
 //cv::namedWindow():函数将会在屏幕上打开一个窗口,窗口名为tree,cv::WINDOW_AUTOSIZE是窗口的属性:窗口的大小与载入的图片大小一致,图片会被缩放大小来适应窗口大小cv::namedWindow("tree", cv::WINDOW_AUTOSIZE);

 函数原型:

void cv::namedWindow(const String &winname,int flags = WINDOW_AUTOSIZE);
函数功能:函数namedWindow创建一个窗口,该窗口可用作图像和跟踪条的占位符。创建的窗口通过窗口名称来引用
参数:winname: 窗口标题,也是用于窗口标识符的窗口名称flags: 窗口标志下面是falgs的枚举类型:enum cv::WindowFlags {cv::WINDOW_NORMAL = 0x00000000,       //用户可以调整窗口的大小(没有限制)/也可以将全屏窗口切换到正常大小cv::WINDOW_AUTOSIZE = 0x00000001,     //用户无法调整窗口大小,窗口大小受显示图像的限制cv::WINDOW_OPENGL = 0x00001000,       //支持opengl的窗口cv::WINDOW_FULLSCREEN = 1,            //将窗口改为全屏cv::WINDOW_FREERATIO = 0x00000100,    //图像尽可能地扩展(没有比例限制)cv::WINDOW_KEEPRATIO = 0x00000000,    //保持图像原有的比例cv::WINDOW_GUI_EXPANDED =0x00000000,  //状态栏和工具栏cv::WINDOW_GUI_NORMAL = 0x00000010    //默认的窗口模式,会在图像显示时以普通窗口的形式呈现,并提供基本的窗口操作,如调整大小、移动和关闭}
返回值:无返回值
         3)cv::imshow()函数
//cv::imshow():函数将会创建一个窗口(如果这个窗口不存在,会自动调用cv::namedWindow()函数来新建一个窗口),调用cv::imshow()会将指定的图片绘制在窗口上cv::imshow("tree", img);

函数原型:


void cv::imshow(const String &winname, InputArray mat);
函数功能: 在指定窗口中显示图像
参数: winname: 指定的窗口对象mat: 展示的图像
返回值: 无返回值
        4)cv::waitKey()函数
//cv::waitKey():系统暂停并等待键盘事件发生(如果传入的参数值大于零,就会等待该值的毫秒时间(如果在等待时间中有键盘事件发生,会立马继续执行后面的程序),然后继续执行后面程序,如果参数设置为0或负数,程序将会无限等待,直到有键盘事件发生)cv::waitKey(0); //cv::waitKey(10000);

 函数原型:

int cv::waitKey	(int delay = 0);
函数功能: 等待键盘事件发生
参数: delay: 以毫秒为单位的延迟。0是代表“永远”的特殊值
返回值:返回按下的键的代码,如果在指定时间之前没有按下键,则返回-1
        5)cv::destroyWindow()函数
//cv::destroyWindow() 关闭指定的窗口并释放相关内存空间cv::destroyWindow("tree");

函数原型:

void cv::destroyWindow(const String &winname);	
函数功能: 销毁指定的窗口
参数:winname: 要销毁的窗口名称
返回值:无返回值

2.使用Opencv加载视频

(1)使用Qt创建一个新项目

(2)在.pro文件中链接OpenCV库

#链接OpenCV头文件
INCLUDEPATH +=/usr/local/include/
INCLUDEPATH +=/usr/local/include/opencv4/
INCLUDEPATH +=/usr/local/include/opencv4/opencv2
#链接OpenCV库文件
LIBS += -L/usr/local/lib -lopencv_gapi \-lopencv_stitching -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired \-lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm \-lopencv_highgui -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hfs \-lopencv_img_hash -lopencv_line_descriptor -lopencv_quality -lopencv_reg \-lopencv_rgbd -lopencv_saliency -lopencv_sfm -lopencv_stereo -lopencv_structured_light \-lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching \-lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot \-lopencv_videostab -lopencv_videoio -lopencv_xfeatures2d -lopencv_shape -lopencv_ml \-lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect \-lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto \-lopencv_photo -lopencv_imgproc -lopencv_core

(3)在mainwindow.cpp中编写代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//新建一个窗口,窗口名为scenery,窗口模式为cv::WINDOW_AUTOSIZEcv::namedWindow("scenery", cv::WINDOW_AUTOSIZE);cv::VideoCapture cap; //cv::VideoCapture类型用于打开视频文件//打开指定的视频文件if(!cap.open("/Users/liwanyu/Downloads/opencvDemo/day1/video/videoload/video/scenery.mp4")){qDebug() << "打开视频文件失败";}//打开网络视频//cap.open("https://vd2.bdstatic.com/mda-njqbvdg1h8kdqez1/720p/h264/1666686182583726512/mda-njqbvdg1h8kdqez1.mp4?v_from_s=hkapp-haokan-hna&amp;auth_key=1703093507-0-0-fc2c4688c205be7eedb5e09162e45f57&amp;bcevod_channel=searchbox_feed&amp;pd=1&amp;cr=2&amp;cd=0&amp;pt=3&amp;logid=1907408427&amp;vid=14746953470406117750&amp;klogid=1907408427&amp;abtest=");cv::Mat frame; //用于保存视频帧//在while循环中循环播放视频while(1){//视频文件按照帧从视频流中读出来,每33毫秒换帧,如果在这33毫秒中有键盘事件发生就退出视频帧播放cap.read(frame); //cap >> frameif(frame.empty()){break;}cv::imshow("scenery", frame);if(cv::waitKey(33)>=0){break;}}cv::destroyWindow("scenery"); //关闭指定的窗口并销毁其内存空间
}MainWindow::~MainWindow()
{delete ui;
}

运行结果:

(4)代码中使用的OpenCV函数分析

        1)cv::VideoCapture

   cv::VideoCapture 

功能:用于从视频文件、图像序列或相机中捕获视频的类

        

Public Member Functions:

默认的空构造:

   

cv::VideoCapture::VideoCapture();

 重载的构造:

​cv::VideoCapture::VideoCapture(const String &filename, int apiPreference = CAP_ANY);

功能:

        打开视频文件或捕获摄像头设备或IP视频流(网络传输视频流),默认使用API首选项(CAP_ANY)进行视频捕获

参数:

        filename要打开的视频文件名、捕获设备的索引号(一般为0表示默认摄像头),或者是 IP 视频流地址

        apiPreference可选参数,用于指定视频捕获 API 的首选项。默认值为 CAP_ANY,表示尝试使用任何可用的视频捕获 API 来打开

 cv::VideoCapture::VideoCapture(const String &filename, int apiPreference, const std::vector<int> &params);

功能: 

         打开视频文件或捕获摄像头设备或IP视频流(网络传输视频流),默认使用API首选项(CAP_ANY)进行视频捕获

参数:       

        filename要打开的视频文件名、捕获设备的索引号(一般为0表示默认摄像头),或者是 IP 视频流地址

        apiPreference可选参数,用于指定视频捕获 API 的首选项。默认值为 CAP_ANY,表示尝试使用任何可用的视频捕获 API 来打开

        params:可选不定参数,以向底层视频捕获库传递附加的特定参数

例如:

       

 cv::VideoCapture cap("video.mp4", cv::CAP_FFMPEG, {cv::CAP_PROP_FRAME_WIDTH, 640, cv::CAP_PROP_FRAME_HEIGHT, 480});

        在此示例中,传递了一组参数来设置所捕获视频帧的宽度和高度。使用了 cv::CAP_PROP_FRAME_WIDTHcv::CAP_PROP_FRAME_HEIGHT,这些常量表示帧的宽度和高度属性,然后将期望的值分别设置为 640 和 480。这意味着设置了捕获的每个视频帧的宽度为 640 像素,高度为 480 像素。

​cv::VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY);

功能:

         打开摄像机进行视频捕获

参数:

        index:捕获设备的索引号,用于指定要打开的特定设备。通常情况下,0 表示默认摄像头,1 表示第二个摄像头,以此类推。如果你的系统上有多个摄像头或其他捕获设备,可以通过指定不同的索引号来选择打开哪个设备

        apiPreference可选参数,用于指定视频捕获 API 的首选项。默认值为 CAP_ANY,表示尝试使用任何可用的视频捕获 API 来打开

​cv::VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY,  int apiPreference, const std::vector<int> &params); 

功能:

        使用API首选项和不定参数打开摄像机进行视频捕获。

参数:      

        index:捕获设备的索引号,用于指定要打开的特定设备。通常情况下,0 表示默认摄像头,1 表示第二个摄像头,以此类推。如果你的系统上有多个摄像头或其他捕获设备,可以通过指定不同的索引号来选择打开哪个设备

        apiPreference可选参数,用于指定视频捕获 API 的首选项。默认值为 CAP_ANY,表示尝试使用任何可用的视频捕获 API 来打开

        params:可选不定参数,以向底层视频捕获库传递附加的特定参数

 默认的析构函数:

virtual cv::VideoCapture::~VideoCapture();

其他成员函数: 

virtual double cv::VideoCapture::get(int propld) const;

功能:

        返回指定的VideoCapture属性

参数:

        propld:要获取属性的标识符(例如,如果propId为CV_CAP_PROP_FRAME_WIDTH,则该函数将返回输入视频流的帧宽度)

返回值:

        返回值类型为double,表示所请求属性的当前值

String cv::VideoCapture::getBackendName()const;

功能:

        用于返回使用的视频捕获后端API的名称

参数:

        无参数

返回值:

        成功:String类型的后端API名称

        失败:NULL

bool cv::VideoCapture::getExceptionMode();

功能:

        用于获取异常模式的状态

参数:

        无参数

返回值:

        返回true,则表示异常模式已启用,即当发生错误时,将抛出异常

        返回false,则表示异常模式已禁用,即当发生错误时,不会抛出异常,而是通过错误码或其他方式通知用户

 virtual bool cv::VideoCapture::grab();

功能:

        用于从输入视频流中抓取一帧图像,但不将其解码

参数:

        无参数

返回值:

        返回true,则表示成功抓取了一帧图像

        返回false,则表示未能成功抓取图像

virtual bool cv::VideoCapture::isOpened()const;

功能:

        用于检查当前视频捕获对象是否成功打开了视频文件或设备

参数:

        无参数

返回值:

        返回true,则表示视频捕获对象已成功打开,并且可以从该对象读取视频帧

        返回false,则表示视频捕获对象无法打开,可能是由于文件路径错误、设备未连接或者不支持的格式等原因

用于打开视频文件或设备的open函数:(open函数的参数和cv::VideoCapture:构造函数的参数一样就不再解释了)

​
virtual bool cv::VideoCapture::open(const String &filename, int apiPreference = CAP_ANY);
virtual bool cv::VideoCapture::open(const String &filename, int apiPreference, const std::vector<int> &params);
virtual bool cv::VideoCapture::open(int index, int apiPreference = CAP_ANY);
virtual bool cv::VideoCapture::open(int index, int apiPreference = CAP_ANY,  int apiPreference, const std::vector<int> &params); 

重载的运算符函数: 

virtual VideoCapture &operator>>(Mat &image);

功能:

        用于从视频流中读取一帧图像并将其存储到提供的Mat对象中

参数:

        image:要存储读取帧的Mat对象。它将存储从视频流中读取的图像数据        

virtual VideoCapture &operator>>(UMat &image);

功能:

        用于从视频流中读取一帧图像并将其存储到提供的UMat对象中

参数:

        image:要存储读取帧的UMat对象。它将存储从视频流中读取的图像数据        

virtual bool cv::VideoCapture::read(OutputArray image);	

功能:

        用于从视频流中读取一帧图像并将其存储在提供的OutputArray对象中

参数:

        image:要存储读取帧的OutputArray对象。它可以是MatUMat或其他可接受输出图像数据的对象类型

返回值:

        返回true,则表示成功读取到一帧图像,并将其存储在提供的OutputArray对象中

    返回false,则表示未能成功读取图像,可能是由于视频结束、读取错误或其他原因

virtual void cv::VideoCapture::release();

功能:

        用于释放视频捕获对象所占用的资源 

参数:

        无参数

返回值:

        无返回值

virtual bool cv::VideoCapture::retrieve(OutputArray image, int flag=0);

功能:

        用于解码和获取当前抓取的视频帧

参数:

        image:要存储解码后图像的OutputArray对象。它可以是MatUMat或其他可接受输出图像数据的对象类型

        falg:可选参数,用于指定附加的操作标志。默认值为0

返回值:

        返回true,则表示成功解码当前抓取的视频帧,并将其存储在提供的OutputArray对象中

        返回false,则表示未能成功解码视频帧

virtual bool cv::VideoCapture::set(int propId, double value);

功能:

        用于设置视频捕获对象的属性值 

参数:

    propId:要设置的属性的标识符。可以使用不同的标识符来设置不同的属性值。例如,如果propIdCV_CAP_PROP_FRAME_WIDTH,则代表设置输入视频流的帧宽度

    value:要设置的属性值

返回值:

        返回true,则表示成功设置属性的值

        返回false,则表示无法设置属性的值,可能是由于不支持的属性或其他原因

void cv::VideoCapture::setExceptionMode(bool enable);

功能:

        用于设置异常模式的状态

参数:

        enable:一个bool值,表示是否启用异常模式。如果enabletrue,则启用异常模式,即当发生错误时,将抛出异常  ;如果enablefalse,则禁用异常模式,即当发生错误时,不会抛出异常,而是通过错误码或其他方式通知用户

返回值:

        无返回值

静态成员函数: 

static bool cv::VideoCapture::waitAny(const std::vector< VideoCapture > &streams, std::vector< int > &readyIndex, int64 timeoutNs=0);

功能:       

        静态成员函数,用于等待多个视频捕获对象中至少一个准备就绪(有可读取的帧)

参数:

        streams:一个包含多个VideoCapture对象的std::vector,表示要等待的视频捕获对象列表。

    readyIndex:一个空的std::vector<int>,用于存储准备就绪的视频捕获对象的索引。准备就绪的对象即有可读取的帧。

    timeoutNs:可选参数,以纳秒为单位指定的超时时间。默认值为0,表示无限等待

返回值:

        返回true,则表示至少一个视频捕获对象已准备就绪。

        返回false,则表示在超时时间内没有可用的视频捕获对象

友元类:

friend class internal::VideoCapturePrivateAccessor

参考文档:

OpenCV: Image file reading and writing

OpenCV: High-level GUI

OpenCV: cv::VideoCapture Class Reference

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 3 Composition API:让组件开发更高效、灵活(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

图解二叉树的Morris(莫里斯)遍历

二叉树的Morris(莫里斯)遍历 本文参考链接&#xff1a;https://leetcode.cn/problems/binary-tree-preorder-traversal/submissions/490846864/ 文章目录 二叉树的Morris(莫里斯)遍历模板代码前序遍历中序遍历后序遍历 Morris 遍历使用二叉树节点中大量指向 null 的指针&…

编程规范:长函数的思考

在工作&#xff0c;我们应该都不想看到非常的长函数。对于一个运行5年左右的项目&#xff0c;极有可能出现这种情况。由于长函数的长、if/else嵌套&#xff0c;导致代码的可读性非常差&#xff0c;这对于项目的维护和开发带来了极大的困难。所以我们应该避免写长函数&#xff0…

人工智能_机器学习070_SVM支持向量机_软间隔及优化_硬间隔_衡量间隔软度_引入松弛变量_理解隔离参数---人工智能工作笔记0110

我们继续说,之前说的C是什么意思? 我们在这个软间隔优化中就可以引出C 可以看到之前我们讨论的问题,都是基于样本点的,完全的线性可分的问题,我们称为硬间隔 可以看到这种,一分就可以,分开,简单分割就可以分开的数据,我们称之为硬间隔 但是可以看到上面这种情况,无论怎么分,都…

第1课 配置FFmpeg+OpenCV开发环境

本教程所对应的SDK下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88657539 本课对应源文件下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88657528 一、配置开发环境 1.下载FFmpegOpenCV开发所用的SDK压缩包&#xff0…

分享70个Java源码总有一个是你想要的

分享70个Java源码总有一个是你想要的 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1s8ZVYHb5B1GgXMlpG-6-Iw?pwd6666 提取码&#xff1a;6666 项目名称 admin、cms、console 等多…

构建创新学习体验:企业培训系统技术深度解析

企业培训系统在现代企业中发挥着越来越重要的作用&#xff0c;它不仅仅是传统培训的延伸&#xff0c;更是技术创新的结晶。本文将深入探讨企业培训系统的关键技术特点&#xff0c;并通过一些简单的代码示例&#xff0c;展示如何在实际项目中应用这些技术。 1. 前端技术&#…

Redis基础-Redis概念及常见命令

1.nosql数据库 NoSQL数据库是一种提供了非关系型数据存储的数据库系统&#xff0c;与传统的关系型数据库&#xff08;如SQL数据库&#xff09;不同。NoSQL数据库的特点是灵活性高&#xff0c;能够处理结构化、半结构化或非结构化数据。它们通常用于大数据和实时Web应用。NoSQL数…

C++面试宝典第9题:找出第K大元素

题目 给定一个整数数组a,同时给定它的大小N和要找的K(1 <= K <= N),请根据快速排序的思路,找出数组中第K大的数(保证答案存在)。比如:数组a为[50, 23, 66, 18, 72],数组大小N为5,K为3,则第K大的数为50。 解析 这道题主要考察应聘者对于快速排序的理解,以及实…

Python 数据分析 Matplotlib篇 时间序列数据绘制折线图(第4讲)

Python 数据分析 Matplotlib篇 时间序列数据绘制折线图(第4讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…

SAE 2.0,让容器化应用开发更简单

作者&#xff1a;邵丹 云原生容器化应用托管模式的演变 云原生这个概念从提出&#xff0c;到壮大&#xff0c;再到今天的极大普及&#xff0c;始终处于一个不断演进和革新的过程中。云原生体系下应用的托管形态是随着企业应用架构在不断演进的。最早的应用大多是集中式、单体…

Bellman_Ford算法总结

知识概览 Bellman_Ford算法适合解决存在负权边的最短路问题&#xff0c;时间复杂度为O(nm)。在存在负权边的最短路问题中&#xff0c;Bellman_Ford算法的效率虽然不如SPFA算法&#xff0c;但是Bellman_Ford算法能解决SPFA算法不能解决的经过不超过k条边的最短路问题。 例题展示…

【c++、数据结构课设】哈夫曼树

时间过的真快&#xff0c;转眼之间一个学期即将结束&#xff0c;想必这个时候大家都在准备各科的课设作业&#xff0c;本期内容是我的数据结构课设&#xff0c;希望能给大家带来帮助&#xff0c;如果有任何不足或需要改进的地方&#xff0c;欢迎各位提出宝贵的意见。 屏幕录制2…

bean生命周期源码(三)

书接上文 文章目录 一、Bean的销毁逻辑1. 简介2. Bean销毁逻辑的注册3. Bean的销毁过程 一、Bean的销毁逻辑 1. 简介 前面我们已经分析完了Spring创建Bean的整个过程的源码&#xff0c;在创建bean的核心方法中doCreateBean这一个核心方法中&#xff0c;在方法的最后面有这么…

pycharm修改项目文件夹名称

目录 1 修改项目文件夹名称 2 修改代码中的项目名称 1 修改项目文件夹名称 选中项目文件夹&#xff0c;右键&#xff0c;选择refactor-rename。 选择rename project&#xff1a; 然后输入新的项目名称。 此时进入资源管理器&#xff0c;修改项目文件夹的名字&#xff0c;完成…

spring aop实际开发中怎么用,Spring Boot整合AOP,spring boot加spring mvc一起使用aop,项目中使用aop

前言&#xff1a;本文不介绍 AOP 的基本概念、动态代理方式实现 AOP&#xff0c;以及 Spring 框架去实现 AOP。本文重点介绍 Spring Boot 项目中如何使用 AOP&#xff0c;也就是实际项目开发中如何使用 AOP 去实现相关功能。 如果有需要了解 AOP 的概念、动态代理实现 AOP 的&…

Spark集群部署与架构

在大数据时代&#xff0c;处理海量数据需要分布式计算框架。Apache Spark作为一种强大的大数据处理工具&#xff0c;可以在集群中高效运行&#xff0c;处理数十TB甚至PB级别的数据。本文将介绍如何构建和管理Spark集群&#xff0c;以满足大规模数据处理的需求。 Spark集群架构…

LLM微调(四)| 微调Llama 2实现Text-to-SQL,并使用LlamaIndex在数据库上进行推理

Llama 2是开源LLM发展的一个巨大里程碑。最大模型及其经过微调的变体位居Hugging Face Open LLM排行榜&#xff08;https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard&#xff09;前列。多个基准测试表明&#xff0c;就性能而言&#xff0c;它正在接近GPT-3.5…

光耦继电器

光耦继电器(光电继电器) AQW282SX 282SZ 280SX 280SZ 284SX 284SZ 212S 212SX 21 2SZ 文章目录 光耦继电器(光电继电器)前言一、光耦继电器是什么二、光耦继电器的类型三、光电耦合器的应用总结前言 光耦继电器在工业控制、通讯、医疗设备、家电及汽车电子等领域得到广泛应…

【隐私保护】Presidio简化了PII匿名化

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…