c++ - 用C++将OpenCV帧写入磁盘:单线程写入速度是否受磁盘吞吐量的限制?

标签 c++ opencv frame frame-rate disk

将OpenCV帧写入磁盘时,我面临一种我认为相当奇怪的行为:如果在SSD或HDD上进行写入,则无法独立于20 fps的速度写入磁盘。但是,这就是问题:如果我使用一个线程写入数据的前一半,而另一个线程写入数据的后一半,那么我可以以两倍的速度(〜40 fps)进行写入。
我正在使用以下代码进行测试:两个std::vector从我的摄像头中填充了1920x1080帧,然后发送到两个不同的线程以写入磁盘。例如,如果我将2个大小为50的 vector 写入磁盘,则可以以大约40 fps的整体速度进行操作。但是,如果我仅使用一个大小为100的 vector ,则该值会减少一半。怎么可能?我以为我会受到磁盘吞吐量的限制,足以写入至少30 fps,但是我缺少了一些东西,我不知道是什么。是否有我没有考虑的其他限制(除了cpu)?

#include "opencv2/opencv.hpp"
#include "iostream"
#include "thread"
#include <unistd.h>
#include <chrono>
#include <ctime>

cv::VideoCapture camera(0);

void writeFrames(std::vector<cv::Mat> &frames, std::vector<int> &compression_params, std::string dir)
{
    for(size_t i=0; i<frames.size(); i++)
    {
        cv::imwrite(dir + std::to_string(i) + ".jpg",
                    frames[i], compression_params);
    }
}

int main(int argc, char* argv[])
{
    camera.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
    camera.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
    camera.set(cv::CAP_PROP_FPS, 30);

    std::vector<int> compression_params;
    compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
    compression_params.push_back(95); // [0 - 100] (100 better), default 95

    size_t vecSizeA = 50;
    size_t vecSizeB = 50;

    std::vector<cv::Mat> framesA, framesB;
    cv::Mat frame;

    std::chrono::system_clock::time_point t0 = std::chrono::system_clock::now();

    for(unsigned int i=0; i<vecSizeA; i++)
    {
        camera >> frame;
        framesA.push_back(frame);
    }

    for(unsigned int i=0; i<vecSizeB; i++)
    {
        camera >> frame;
        framesB.push_back(frame);
    }

    std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();

    std::thread trA(writeFrames, std::ref(framesA), std::ref(compression_params), "/tmp/frames/A/");
    std::thread trB(writeFrames, std::ref(framesB), std::ref(compression_params), "/tmp/frames/B/");

    trA.join();
    trB.join();

    std::chrono::system_clock::time_point t2 = std::chrono::system_clock::now();

    double tr = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count() / 1000.0;
    double tw = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() / 1000.0;

    std::cout << "Read fps: " << (vecSizeA + vecSizeB) / tr << std::endl;
    std::cout << "Write fps: " << (vecSizeA + vecSizeB) / tw << std::endl;

    return 0;
}
编辑:万一它不是很清楚,我正在寻找一种写速度至少达到30 fps的方法。磁盘可以解决这个问题(如果不是这种情况,我们将无法以30fps的速度录制视频),所以我的局限性来自于我的代码或我所缺少的东西。

最佳答案

因为2个线程同时达到相同的功能,并且看起来比1个线程快。您的线程的联接位于同一位置。如果像这样使用它们,您将获得与一个线程相同的fps:

    std::thread trA(writeFrames, std::ref(framesA), std::ref(compression_params), "/tmp/frames/A/");

    trA.join();

    std::thread trB(writeFrames, std::ref(framesB), std::ref(compression_params), "/tmp/frames/A/");

    trB.join();
您也可以检查here以了解更多信息。

关于c++ - 用C++将OpenCV帧写入磁盘:单线程写入速度是否受磁盘吞吐量的限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62995295/

相关文章:

c++ - 从带括号的模板参数列表到 "steal"逗号的类似函数的宏是否合法?

c++ - 无法生成 Doxygen 图

C++:类如何将自身加载到内存中以增加全局变量?

html - 如果你只知道它的宽度,如何为 img 添加一个花哨的框架?

ios - 如何在 superview 中定位 UIView?

android - QML 设备部署

c - 在 Opencv 中使用 IPL_DEPTH_32f

python - 如何在OpenCV中平移和缩放视频?

c++ - Opencv cv::垫公差区间

iOS:加载表格 View 时无法更新单元格中 View 的框架