使用 OpenCV 进行轮廓处理和图像保存

使用 OpenCV 进行轮廓处理和图像保存

在这篇博客中,我们将展示如何使用 OpenCV 库来处理图像中的轮廓,并将处理结果保存为带有时间戳的图片。我们还将介绍如何在处理图像时应用一些条件来进行进一步的操作。

前置条件

在开始之前,请确保您已经安装了 OpenCV 库。如果尚未安装,可以通过以下命令安装:

pip install opencv-python

代码实现

包含必要的库

首先,我们需要包含必要的头文件:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <filesystem>
#include <ctime>
设置命名空间和常量

为了简化代码,我们将 std::filesystem 命名空间设置为 fs。另外,我们还定义了一个常量 limitHeight,它将用于设置某种模式:

namespace fs = std::filesystem;

struct MyThread {
    int mode;
};

const int limitHeight = 1;
主处理函数

以下是处理轮廓和保存图像的主函数。该函数接受一帧图像 frame2 和缩小后的图像 ZoomOutimage 作为输入,并将结果保存到指定文件夹中:

void processContours(
    const cv::Mat& frame2, 
    const cv::Mat& ZoomOutimage, 
    MyThread& mythread, 
    std::string& nextColor
) {
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(frame2, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    int Ycount = 0;
    cv::Mat output_image = ZoomOutimage.clone();
    double total_white_area = 0;

    for (const auto& contour : contours) {
        cv::RotatedRect rect = cv::minAreaRect(contour);
        cv::Point2f box[4];
        rect.points(box);
        std::vector<cv::Point> box_points(box, box + 4);

        float width = rect.size.width;
        float height = rect.size.height;

        if (width == 0 || height == 0) {
            continue;
        }

        float aspect_ratio = std::max(width, height) / std::min(width, height);
        double area = cv::contourArea(contour);

        std::cout << "矩形大小: 宽 = " << width << ", 高 = " << height << ", 面积 = " << area << std::endl;

        total_white_area += area;

        if (0 <= aspect_ratio && aspect_ratio <= 20 && area > 0) {
            Ycount++;
            cv::polylines(output_image, box_points, true, cv::Scalar(0, 255, 0), 2);
        }
    }

    std::cout << "满足条件的矩形个数: " << Ycount << std::endl;
    std::cout << "在白色颜色范围内的总面积: " << total_white_area << std::endl;

    cv::Mat combined_image;
    cv::hconcat(std::vector<cv::Mat>{ZoomOutimage, frame2, output_image}, combined_image);

    std::time_t now = std::time(nullptr);
    char buffer[80];
    std::strftime(buffer, sizeof(buffer), "%Y%m%d_%H%M%S", std::localtime(&now));
    std::string current_time(buffer);

    cv::putText(combined_image, current_time, cv::Point(10, combined_image.rows - 10), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 255, 255), 1);

    std::string folder = "imageY";
    if (!fs::exists(folder)) {
        fs::create_directory(folder);
    }

    std::string filename = folder + "/output_image_" + current_time + ".jpg";
    cv::imwrite(filename, combined_image);

    if (Ycount >= 1) {
        mythread.mode = limitHeight;
        nextColor = "null";
        std::cout << "recognize blue" << std::endl;
        return;
    }
}
主要步骤说明
  1. 查找轮廓:使用 cv::findContours 函数在二值化图像 frame2 中查找所有轮廓。
  2. 初始化变量:定义计数器 Ycount 和结果图像 output_image,并初始化总面积 total_white_area
  3. 遍历轮廓:遍历所有轮廓,计算每个轮廓的最小外接矩形的宽、高和面积,并输出这些信息。
  4. 绘制满足条件的矩形:根据长宽比和面积条件,筛选出符合要求的矩形,并将其绘制在结果图像 output_image 上。
  5. 合并图像并添加时间戳:将原图、二值化图像和结果图像横向合并,并在合并后的图像上添加当前时间戳。
  6. 创建保存文件夹并保存图像:检查 imageY 文件夹是否存在,不存在则创建。然后使用时间戳作为文件名的一部分,将处理后的图像保存到该文件夹中。
  7. 设置模式:如果找到满足条件的矩形,则设置 mythread.modelimitHeight 并返回。

通过这篇博客,我们展示了如何使用 OpenCV 进行图像处理、轮廓分析以及结果保存。希望这些内容对您有所帮助。欢迎在评论区留言讨论!

            std::vector<std::vector<cv::Point>> contours;
            cv::findContours(frame2, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

            // 初始化计数器和结果图像
            int Ycount = 0;
            cv::Mat output_image = ZoomOutimage.clone();
            double total_white_area = 0;

            // 遍历所有轮廓
            for (const auto& contour : contours) {
                // 获取最小外接矩形
                cv::RotatedRect rect = cv::minAreaRect(contour);
                cv::Point2f box[4];
                rect.points(box);
                std::vector<cv::Point> box_points(box, box + 4);

                // 计算长宽比和面积
                float width = rect.size.width;
                float height = rect.size.height;

                // 检查是否有零值
                if (width == 0 || height == 0) {
                    continue;
                }

                float aspect_ratio = std::max(width, height) / std::min(width, height);
                double area = cv::contourArea(contour);

                // 输出矩形的大小
                std::cout << "矩形大小: 宽 = " << width << ", 高 = " << height << ", 面积 = " << area << std::endl;

                // 输出总面积
                total_white_area += area;

                // 检查长宽比和面积条件
                if (2 <= aspect_ratio && aspect_ratio <= 15 && area > 500) {
                    Ycount++;
                    cv::polylines(output_image, box_points, true, cv::Scalar(0, 255, 0), 2);
                }
            }

            // 显示结果
            std::cout << "满足条件的矩形个数: " << Ycount << std::endl;
            std::cout << "在白色颜色范围内的总面积: " << total_white_area << std::endl;

            // 将每一步处理的图像横向并列
            cv::Mat combined_image;
            cv::hconcat(std::vector<cv::Mat>{ZoomOutimage, frame2, output_image}, combined_image);

            // 获取当前时间
            std::time_t now = std::time(nullptr);
            char buffer[80];
            std::strftime(buffer, sizeof(buffer), "%Y%m%d_%H%M%S", std::localtime(&now));
            std::string current_time(buffer);

            // 在图像上绘制时间戳
            cv::putText(combined_image, current_time, cv::Point(10, combined_image.rows - 10), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 255, 255), 1);

            // 使用时间戳命名文件
            std::string filename = "output_image_" + current_time + ".jpg";

            // 保存结果图像
            cv::imwrite(filename, combined_image);



            if(Ycount>=1){
                mythread.mode=limitHeight;
                nextColor="null";
                cout<<"recognize blue"<<endl;
                return;
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元素之窗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值