C++ 多线程 4K→ 8K (resize)

#include <opencv2/opencv.hpp>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <iostream>
#include <filesystem>
#include <chrono>

using namespace cv;
using namespace std;

// 全局变量
std::atomic<bool> processingComplete(false);
std::atomic<int> frameCount(0);
std::queue<Mat> frameQueue;
std::mutex queueMutex;
std::condition_variable queueCondVar;

class ThreadPool {
public:
    ThreadPool(size_t numThreads) {
        for (size_t i = 0; i < numThreads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(this->queueMutex);
                        this->condVar.wait(lock, [this] { return this->stop || !this->tasks.empty(); });

                        if (this->stop && this->tasks.empty()) return;

                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }
                    task();
                }
                });
        }
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            stop = true;
        }
        condVar.notify_all();
        for (std::thread& worker : workers) {
            worker.join();
        }
    }

    template <class F>
    void enqueue(F&& f) {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            tasks.push(std::forward<F>(f));
        }
        condVar.notify_one();
    }

private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;
    std::mutex queueMutex;
    std::condition_variable condVar;
    bool stop = false;
};

// 图像处理函数
void processImage(const string& inputPath) {
    VideoCapture cap(inputPath);
    if (!cap.isOpened()) {
        cerr << "Error: Unable to open the video file!" << endl;
        return;
    }

    int width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
    int height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));

    while (true) {
        Mat frame;
        {
            bool ret = cap.read(frame);
            if (!ret) break;

            // 图像大小调整
            Mat resizedFrame;
            resize(frame, resizedFrame, Size(width * 2, height * 2), 0, 0, INTER_CUBIC);
            //resize(frame, resizedFrame, Size(width * 2, height * 2), 0, 0, INTER_LANCZOS4);

            // 将帧加入队列
            {
                std::lock_guard<std::mutex> lock(queueMutex);
                frameQueue.push(resizedFrame);
            }
            queueCondVar.notify_one();
        }
    }

    processingComplete = true;
    queueCondVar.notify_all();
    cap.release();
}

// 显示图像函数
void displayImage() {
    int frameIdx = 0;
    double startTime = (double)getTickCount();

    while (true) {
        Mat frame;
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            queueCondVar.wait(lock, [] { return !frameQueue.empty() || processingComplete; });

            if (frameQueue.empty() && processingComplete) break;

            frame = frameQueue.front();
            frameQueue.pop();
        }

        imshow("Processed Image", frame);
        frameIdx++;

        // 帧率计算
        double elapsedTime = ((double)getTickCount() - startTime) / getTickFrequency();
        cout << "Frame rate: " << frameIdx / elapsedTime << " FPS" << endl;

        if (waitKey(1) == 'q') break;
    }

    destroyAllWindows();
}

int main(int argc, char** argv) {

    string inputPath = "D:\\BaiduNetdiskDownload\\Reset_2022_E01_4K.mp4";

     输出文件夹
    //string outputFolder = "output";
    //if (!fs::exists(outputFolder)) {
    //    fs::create_directory(outputFolder);
    //}

    // 初始化线程池,假设使用4个线程
    ThreadPool pool(8);

    // 启动图像处理线程和显示线程
    pool.enqueue([&] { processImage(inputPath); });
    pool.enqueue(displayImage);

    // 等待所有线程完成
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值