当前位置: 首页 > article >正文

opencv学习笔记(3):图像和视频的读取(C++)

我们知道,OpenCV是一个计算机视觉的开源库,它最基本也最重要的功能肯定是对图像和视频的处理。这个章节学习基本的图像和视频的读取。

1. 图像读取与保存:

1.1 图像读取:

在OpenCV中,使用cv::imread()函数来读取和加载图像,该函数的形式如下。

Mat cv::imread(const String & filename, int flags = IMREAD_COLOR)

可以看到,imread()函数的定义非常简单,其解析如下。

返回值Mat 类型:返回读取的图像,读取图像失败时返回一个空的矩阵对象(Mat::data == NULL)。
参数filename:读取图像的文件名,可以使用相对路径或者绝对路径,但必须带完整的文件扩展名(图像格式后缀)。
参数flags:一个读取标记,用于选择读取图像的方式,默认值为IMREAD_COLOR,flags值的设定与用什么颜色格式读取图像有关。

下面举例

(确保你已经配置好了opencv环境)

//使用VS时的头文件
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

//使用Qt时的头文件
#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;


void test01()
{
    // 1.读取图像
    // cv::imread 功能是加载图像文件成为一个Mat对象。
    Mat image = imread("C:/Users/27844/Desktop/icon.jpg",IMREAD_GRAYSCALE);
    if (image.empty())
    {
        cout << "图片为空!" << endl;
        return;
    }

    // 2.显示图像
    // cv::namedWindow的功能是创建一个OpenCV窗口,它是由OpenCV自动创建与释放,用户无需销毁它。
    namedWindow("window", WINDOW_AUTOSIZE);

    imshow("window", image);

    // waitKey(0); 等待键盘输入,不加这句,窗口会一闪而逝
    waitKey(0);
}

下面为代码中用到的函数做解释: 

  • imshow():用来显示图像的函数。函数定义为cv::imshow ( const String & winname, InputArray mat )。参数const String & winname为显示的窗口名,可以使用cv::namedWindow()函数创建窗口,如不创建,imshow()函数将自动创建;参数InputArray mat为待显示的图像。需要注意的是,imshow()函数之后必须有waitKey()函数,否则显示窗口将一闪而过,不会驻留屏幕。inputArray这个接口类可以是Mat、Mat_<T>、Mat_<T, m, n>、vector<T>、vector<vector<T>>、vector<Mat>,也就意味着函数的参数类型是InputArray型时,把上述几种类型作为参数都可以。另外,OutputArrayOfArrays、InputOutputArray、InputOutputArrayOfArrays都是OutputArray的别名。
  • waitKey():OpenCV中的内置函数,语句waitKey(0)表示“暂停程序,等待一个按键输入”,也就是说,当程序执行到waitKey(0)时暂停运行,只有当用户按下一个按键时,它才会继续运行。参数中的 0 表示等待时间,0表示无限等待。

1.2 图像保存:   

同图像读取类似,OpenCV中使用cv::imwrite()函数实现将图像保存到指定的文件,该函数定义如下。

bool cv::imwrite(const String & filename,
InputArray img,
const std::vector<int> & params = std::vector<int>() );

imwrite()函数的参数解析如下。

  • const String & filename:需要保存图像的文件名,要保存图像为哪种格式,就带什么扩展名。
  • InputArray img:要保存的图像。
  • const Std::Vector <int> & params:表示为特定格式保存的参数编码。

举例: 

    Mat image(2,2,CV_8UC3,Scalar(0,255,255));
    cout<<"矩阵元素"<<endl<<image<<endl;
    //   将图像保存
    if(imwrite("D:/test.jpg",image))
    {
        cout<<"图片保存成功!"<<endl;
    }
    else
    {
        cout<<"图片保存失败!"<<endl;
    }

2. 视频读取与保存:

 2.1视频的读取:

 opencv使用 cv::VideoCapture类来读取视频。

视频是由一帧一帧的画面构成,读取视频的过程就是一帧一帧地读取视频帧,读一帧,放到一个Mat对象里面,然后在进行显示。

视频的读取操作步骤如下:

(1)创建cv::VideoCapture的对象。

(2)验证视频读取是否成功。
(3)验证完成,开始读取视频。

VideoCapture对象的创建方式有三种,如下面代码所示: 


    // VideoCapture对象创建
    // (1)从文件读取视频
    VideoCapture capture("");

    // (2)从视频捕捉设备读取
    //  这种情况下,可以给出一个标识符,用于表示想要访问的视频捕捉设备,及其与操作系统的握手方式。
    //  对于视频捕捉设备而言,这个标识符就是一个标识数字——如果只有一台视频捕捉设备,那么就是0,
    //  如果系统中有多台视频捕捉设备,那么增加标识数字的值即可。
    VideoCapture capture2(0);

    // (3)仅创建一个捕获对象,而不提供任何关于打开的信息。
    // 对象创建以后通过成员函数open()来设定打开的信息。open()操作也有以下两种方式。
    VideoCapture cap;
    cap.open( "my_video.avi"); //第一种方式打开视频文件
    cap.open(0); //第二种方式打开视频捕捉设备

    // 打开视频后,需要将视频帧读取到cv::Mat矩阵中,共有两种方式,一种是read()操作,另一种是>>操    
    // 作。示例如下。
    cv::Mat frame;
    cap.read(frame); //读取方式一
    cap >> frame; //读取方式二

示例代码:

//(1)创建cv::VideoCapture的对象。

cv::VideoCapture capture("D:/images/test1.mp4");
//参数类型为const string&,即从文件中读取,若设置为0则读取视频捕捉设备。

//(2)验证视频读取是否成功。

if (!capture.isOpened())
{
    std::cout << "Vidoe open failed!" << std::endl;
    return -1;
}
//(3)验证完成,开始读取视频。

cv::Mat frame;
capture >> frame;

 2.2视频的保存:

opencv一般使用 cv::VideoWirter类来保存视频。视频的保存也是一帧一帧来保存的。

(VideoWirter与VideoCapture一般配合使用,类似于文件的读写操作)

cv::VideoWriter类的对象的创建有两种方式,第一种是使用构造函数,第二种是使用open()函数,具体示例如下。

第一种方式:

     cv::VideoWriter out(
     const string& filename, // 输出文件名
     int fourcc, // 编码形式,使用 CV_FOURCC()宏
     double fps, // 输出视频帧率
     cv::Size frame_size, // 单帧图像的大小
     bool is_color = true // 如果是false,则可传入灰度图像,true为彩色图像
);


第二种方式:

     cv::VideoWriter out;
     out.open(
     "my_video.mpg", //输出文件名
     CV_FOURCC('D','I','V','X'), // MPEG-4 编码
     30.0, // 输出视频帧率 
     cv::Size( 640, 480 ), // 单帧图像分辨率为 640像素×480像素
     true // 只可传入彩色图像,false为灰度图像
);


其中需要注意的是FOURCC编码形式,操作时常用以下函数把4个字符连接起来形成一个FOURCC 码,形式为cv::VideoWriter::fourcc(char c1,char c2,char c3,char c4)。

常用的格式有如下几种。

CV_FOURCC('P','I','M','1') = MPEG-1 codec。
CV_FOURCC('M','J','P','G') = motion-jpeg codec。
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec。
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec。
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec。


向创建的cv::VideoWriter对象写入图像也有两种方式,即write()操作和<<操作,示例如下。

cv::VideoWriter::write(
    const Mat& image // 写入图像作为下一帧
);
out << frame;

示例:

#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

void function()
{
VideoCapture video("C:/Users/27844/Desktop/video1.mp4");

    if(!video.isOpened())
    {
        cout<<"video open false"<<endl;
        return;
    }
    Mat img;
    namedWindow("video test");
    int frame_num = video.get(CAP_PROP_FRAME_COUNT);
    cout<<"this video frame conut:"<<frame_num<<endl;

    // 1.5.2 VideoWriter对象创建
    // cv::VideoWriter类用于写入视频,该类使用起来比cv::VideoCapture类稍微复杂一些。
    // (1)构造函数
    VideoWriter out("C:/Users/27844/Desktop/out.mp4",
                      VideoWriter::fourcc('D','I','V','X'),
                      video.get(CAP_PROP_FPS),
                      Size(video.get(CAP_PROP_FRAME_WIDTH),video.get(CAP_PROP_FRAME_HEIGHT)),
                      true
                      );
    while(1)
    {
        video.read(img);
        if(img.empty())
        {
            cout<<"over"<<endl;
            return;
        }
        //显示帧图像
        imshow("video test",img);
        if (waitKey(10) == 'q') break;
        //保存图像
        out<<img;
    }


}


http://www.kler.cn/a/369034.html

相关文章:

  • Hive的数据存储格式
  • 基于SpringCloud的WMS管理系统源码
  • git push关联的远程仓库
  • 图文详解ChatGPT-o1完成论文写作的全流程
  • 铜业机器人剥片 - SNK施努卡
  • 数据库文档插件 screw
  • 【AIGC】ChatGPT提示词Prompt精确控制指南:Scott Guthrie的建议详解与普通用户实践解析
  • 26.Redis主从架构
  • Hadoop-001-本地虚拟机环境搭建
  • oracle 行转列(PIVOT 多个行数据按照指定的列进行汇总) 列转行(UNPIVOT)
  • RHCE笔记-NFS服务
  • 第十七周:机器学习
  • 2025年软考高级哪个最简单?
  • 重构商业生态:DApp创新玩法与盈利模式的深度剖析
  • c语言中整数在内存中的存储
  • 7、基于爬虫+Flask+Echarts+MySQL的网易云评论可视化大屏
  • 【MySQL】提高篇—数据完整性与约束:主键、外键、唯一约束和检查约束的概念
  • Linux 命令行查看当前目录的总大小/总磁盘空间/磁盘清理
  • Oracle 19c RAC删除多余的PDB的方式
  • Vue 3 对接保利威云点播播放器实践
  • 使用pandas进行数据分析
  • 【Linux】————进程间通信(匿名管道)
  • 数据结构(JAVA)JDK17语法新增特性
  • java spark解决文件读取乱码问题
  • rtp协议:rtcp包格式和传输间隔
  • 【Python】Python面向对象编程进阶:继承、多态与封装