• C++ opencv基本用法【学习笔记(九)】


    这篇博客为修改过后的转载,因为没有转载链接,所以选了原创

    一、vs code 结合Cmake debug

    1.1 配置tasks.json

    文件架构如下:
    在这里插入图片描述
    需要注意"-DCMAKE_BUILD_TYPE=Debug" 要设置为Debug模式。

    {
    	"version": "2.0.0",
    	"tasks": [
    		{
    			// cmake配置
    			"type": "cppbuild",
    			"label": "CMake配置",
    			"command": "cmake", // cmake命令
    			"args": [
    				"-S .", // 源码目录
    				"-B build", // 编译目录
    				"-DCMAKE_BUILD_TYPE=Debug" // 编译类型
    			],
    			"options": {
    				"cwd": "${workspaceFolder}" // 工作目录
    			},
    			"problemMatcher": [
    				"$gcc"
    			],
    			"group": "build",
    		},
    		{
    			// cmake编译
    			"type": "cppbuild",
    			"label": "CMake编译",
    			"command": "cmake", // cmake命令
    			"args": [
    				"--build", // 编译
    				"build", // 编译目录
    			],
    			"options": {
    				"cwd": "${workspaceFolder}" // 工作目录
    			},
    			"problemMatcher": [
    				"$gcc"
    			],
    			"group": "build",
    			"dependsOn": [
    				"CMake配置" // 依赖CMake配置,先执行CMake配置
    			]
    		},
    		{
    			// 删除build目录
    			"type": "shell",
    			"label": "删除build目录",
    			"command": "rm -rf build",
    			"options": {
    				"cwd": "${workspaceFolder}" // 工作目录
    			},
    			"problemMatcher": [
    				"$gcc"
    			],
    			"group": "build",
    			
    			
    		}
    	]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    1.2 配置launch.json

    {
        // 使用 IntelliSense 了解相关属性。 
        // 悬停以查看现有属性的描述。
        // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
        "version": "0.2.0",
        "configurations": [
            {
                "name": "CMake调试",
                "type": "cppdbg",
                "request": "launch",
                "program": "${workspaceFolder}/build/cmake_debug", // 编译后的程序,需要结合CMakeLists.txt中的add_executable()函数
                "args": [],
                "stopAtEntry": false,
                "cwd": "${workspaceFolder}",
                "environment": [],
                "externalConsole": false,
                "MIMode": "gdb",
                "miDebuggerPath": "/usr/bin/gdb",
                "setupCommands": [
                    {
                        "description": "Enable pretty-printing for gdb",
                        "text": "-enable-pretty-printing",
                        "ignoreFailures": true
                    }
                ],
                "preLaunchTask": "CMake编译"
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    二、图片、视频、摄像头读取显示

    2.1 读取图片并显示

    // 使用imread函数读取图片,和Python用法类似
    // 读取的数据保存在Mat类型的变量image中,Mat是opencv中的图像数据结构,类似numpy中的ndarray
    cv::Mat image = cv::imread("图片路径");
    
    // 输出数据,以numpy和Python list格式输出
    std::cout << cv::format(image, cv::Formatter::FMT_NUMPY) << std::endl;
    std::cout << cv::format(image, cv::Formatter::FMT_PYTHON) << std::endl;
    
    // 判断图像是否读取成功,返回true表示失败
    if (image.empty())
    {
      std::cout << "无法读取图片"  << std::endl;
      return 1;
    } 
    // imshow显示图像
    cv::imshow("opencv demo", image);
    // 保存图像
    cv::imwrite("./output/gray_image.jpg", gray_image);
    
    // 等待按键
    cv::waitKey(0); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2.2 读取视频文件并显示

    // 读取视频:创建了一个VideoCapture对象,参数为视频路径
    cv::VideoCapture capture("视频路径");
    
    // 判断视频是否读取成功,返回true表示成功
    if (!capture.isOpened())
    {
      std::cout << "无法读取视频"  << std::endl;
      return 1;
    }
    
    // 读取视频帧,使用Mat类型的frame存储返回的帧
    cv::Mat frame;
    // 循环读取视频帧
    while (true)
    {
      // 读取视频帧,使用 >> 运算符或者read()函数,他的参数是返回的帧
      capture.read(frame);
      // capture >> frame;
      
      // 显示视频帧
      cv::imshow("opencv demo", frame);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.3 读取摄像头并写入文件

    // 读取视频:创建了一个VideoCapture对象,参数为摄像头编号
    cv::VideoCapture capture(0);
    
    // 写入MP4文件,参数分别是:文件名,编码格式,帧率,帧大小  
    cv::VideoWriter writer("record.mp4", cv::VideoWriter::fourcc('H', '2', '6', '4'), 20, cv::Size(640, 480));
    
    // 写入视频
    writer.write(frame);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    三、图片基本操作

    3.1 颜色转换

    // BGR -> Gray
    // 三个参数分别是输入图像、输出图像、转换方式
    cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    // BGR -> HSV,Hue(色调)、Saturation(饱和度)、Value(明度)
    cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV);
    // BGR -> RGB
    cv::cvtColor(src, rgb, cv::COLOR_BGR2RGB);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.2 图像filtering

    // 三个参数分别是输入图像、输出图像、卷积核大小
    cv::GaussianBlur(src, blur, cv::Size(7, 7), 0);
    // 膨胀
    // 三个参数分别是输入图像、输出图像、卷积核大小
    cv::dilate(src, dilate, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)));
    // 腐蚀
    // 三个参数分别是输入图像、输出图像、卷积核大小
    cv::erode(src, erode, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.3 形状调整

    // ======== resize ========
    // 三个参数分别是输入图像、输出图像、输出图像大小
    cv::resize(src, resize, cv::Size(320, 240));
    
    // ======== copy ========
    cv::Mat copy;
    src.copyTo(copy);
    // ======== ROI裁剪 ========
    cv::Rect rect(100, 100, 200, 100); // x, y, width, height
    cv::Mat roi = src(rect);
    cv::imwrite("./output/3.roi.jpg", roi);
    
    // ======== 拼接 ========
    cv::Mat dog_img = cv::imread("./media/dog.jpg");
    cv::Mat dog_resize;
    cv::resize(dog_img, dog_resize, cv::Size(320, 240));
    
    // 水平拼接,需要保证两张图片的高度(rows)一致
    cv::Mat hconcat_img;
    cv::hconcat(resize, dog_resize, hconcat_img);
    cv::imwrite("./output/3.hconcat.jpg", hconcat_img);
    
    // 或者使用vector方式
    std::vector<cv::Mat> imgs{resize, dog_resize, resize, dog_resize};
    cv::Mat hconcat_img2;
    cv::hconcat(imgs, hconcat_img2);
    cv::imwrite("./output/3.hconcat2.jpg", hconcat_img2);
    
    // 数组方式
    cv::Mat imgs_arr[] = {dog_resize, resize, dog_resize, resize};
    cv::Mat hconcat_img3;
    cv::hconcat(imgs_arr, 4, hconcat_img3); // 4是数组长度
    cv::imwrite("./output/3.hconcat3.jpg", hconcat_img3);
    
    // 垂直拼接,需要保证两张图片的宽度(cols)一致
    cv::Mat vconcat_img;
    cv::vconcat(resize, dog_resize, vconcat_img);
    cv::imwrite("./output/3.vconcat.jpg", vconcat_img);
    
    // ======== 翻转 ========
    cv::Mat flip;
    // 三个参数分别是输入图像、输出图像、翻转方向
    cv::flip(src, flip, 1); // 1表示水平翻转,0表示垂直翻转,-1表示水平垂直翻转
    
    // ======== 旋转 ========
    cv::Mat rotate;
    // 三个参数分别是输入图像、输出图像、旋转角度
    cv::rotate(src, rotate, cv::ROTATE_90_CLOCKWISE); // 顺时针旋转90度
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    3.4 绘制

    // 创建一个黑色图像,参数分别是图像大小、图像类型,CV_8UC3表示8位无符号整数,3通道
    cv::Mat image = cv::Mat::zeros(cv::Size(600, 600), CV_8UC3);
    
    // 绘制直线,参数分别是图像、起点、终点、颜色、线宽、线型
    cv::line(image, cv::Point(50, 50), cv::Point(350, 250), cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
    // 绘制矩形,参数分别是图像、左上角、右下角、颜色、线宽、线型
    cv::rectangle(image, cv::Point(50, 50), cv::Point(350, 250), cv::Scalar(0, 255, 0), 2, cv::LINE_AA);
    // 绘制圆形,参数分别是图像、圆心、半径、颜色、线宽、线型
    cv::circle(image, cv::Point(200, 150), 100, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);
    // 实心
    cv::circle(image, cv::Point(200, 150), 50, cv::Scalar(255, 0, 0), -1, cv::LINE_AA);
    
    // ================== 多边形 ==================
    cv::Point points[2][4]; // 定义两个多边形的顶点数组
    // 第一个多边形的顶点
    points[0][0] = cv::Point(100, 115);
    points[0][1] = cv::Point(255, 135);
    points[0][2] = cv::Point(140, 365);
    points[0][3] = cv::Point(100, 300);
    // 第二个多边形的顶点
    points[1][0] = cv::Point(300, 315);
    points[1][1] = cv::Point(555, 335);
    points[1][2] = cv::Point(340, 565);
    points[1][3] = cv::Point(300, 500);
    // ppt[] 要同时添加两个多边形顶点数组的地址)
    const cv::Point *pts_v[] = {points[0], points[1]};
    // npts_v[]要定义每个多边形的定点数
    int npts_v[] = {4, 4};
    // 绘制多边形,参数分别是图像、顶点数组、顶点数、是否闭合、颜色、线宽、线型
    cv::polylines(image, pts_v, npts_v, 2, true, cv::Scalar(255, 0, 255), 2, 8, 0);
    
    // ================== 使用vector绘制多边形 ==================
    std::vector<cv::Point> points_v;
    // 随机生成5个点
    for (int i = 0; i < 5; i++)
    {
      points_v.push_back(cv::Point(rand() % 600, rand() % 600));
    }
    // 绘制多边形,参数分别是图像、顶点数组、是否闭合、颜色、线宽、线型
    cv::polylines(image, points_v, true, cv::Scalar(255, 0, 0), 2, 8, 0);
    
    
    // ================== 绘制文字 ==================
    // 参数分别是图像、文字、文字位置、字体、字体大小、颜色、线宽、线型
    cv::putText(image, "Hello World!", cv::Point(400, 50), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255, 255, 255), 2, 8, 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    四、RTSP 视频流

    4.1 本机构造RTSP视频流(optional)

    # Ubuntu安装ffmpeg
    sudo apt-get install ffmpeg
    
    # 赋予权限
    chmod +x rtsp-simple-server
    chmod +x start_server.sh
    # 运行服务
    ./start_server.sh
    
    # 退出服务
    pkill rtsp-simple-server
    pkill ffmpeg
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.2 使用ffmpeg作为视频解码

    // CAP_FFMPEG:opencv 使用ffmpeg解码
    cv::VideoCapture stream1 = cv::VideoCapture("rtsp地址", cv::CAP_FFMPEG);
    
    • 1
    • 2

    五、人脸检测小例子

    附件位置:5.face_detection

  • 相关阅读:
    JAVA毕设项目芮城县十全十美火锅店点餐系统(java+VUE+Mybatis+Maven+Mysql)
    虚函数表存储的位置(解析C++内存分配及其编译分段)
    阿里图标库在旧有的iconfont中添加新的图标
    5进程创建FORK
    Springboot 实践(12)RabbitMq server 安装调试(Windows环境)
    字符集导致19c集群安装故障
    lombok总结
    【JAVA】快速排序
    JAVA面试题JVM篇(三)
    pytorch之数据类型tensor
  • 原文地址:https://blog.csdn.net/qq_23022733/article/details/134393380