加快在OpenCV中将图像写入硬盘

PsP*_*PsP 6 c++ qt opencv qthread qtcore

我正在使用50 fps的摄像头(在Ubuntu环境和Qt框架中),每隔20 ms,我就会得到一个帧来处理.

我写了一个代码来从相机读取图像,然后将它们存储在硬盘中.

while(3.14)
{
 cv::Mat Camera_Image = Capture_Image();
 double T1 = (double)cv::getTickCount();
 cv::imwrite (STORE_ADDRESS,Camera_Image);
 T1 = (((double)cv::getTickCount() -T1)*1000)/cv::getTickFrequency();
 print(T1);
}
Run Code Online (Sandbox Code Playgroud)

当我看到输出时,对于2048*1080图像尺寸,将单个图像写入硬盘的时间约为30毫秒.每个图像都是单通道(灰度)但我在硬盘中以.jpg格式编写它们.硬盘中每个图像的大小约为500K字节.

由于我在大约20毫秒内捕获一帧,我无法将它们全部写入硬盘实时.我已经使用Qthread编写了我的代码并创建了一个队列来查看是否有任何改进,但结果是相同的,它只是一个内存开销.

是否有可能改变这种情况,或使用其他库将这些图像更快地写入硬盘?如果可以的话,我也更喜欢Qt解决方案......

另外我需要将每一帧写入硬盘,所以请不要使用Motion压缩算法,因为它们不适用于我的情况....

代码:Mainwindow.cpp

 Qlist<cv::Mat> FINAL_IM_VEC;
MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);

  IMREAD *IMR = new IMREAD(this);   // an instance of IMREAD Class which reads camera frames
  IMWRITE *IMW = new IMWRITE(this);  // an instance of IMWRITE Class which Writes camera frames into hard disk
  QThread *IMAGE_READ_Thread = new QThread(this);
  QThread *Image_Store_Thread = new QThread(this);
  connect(IMAGE_READ_Thread,SIGNAL(started()),IMR,SLOT(IMREAD_Process()));
  connect(Image_Store_Thread,SIGNAL(started()),IMW,SLOT(IMWrite_Process()));
  IMR.moveToThread(IMAGE_READ_Thread);
  IMW.moveToThread(Image_Store_Thread);
  IMAGE_READ_Thread->start();
  Image_Store_Thread->start();
}
Run Code Online (Sandbox Code Playgroud)

imread.hpp

class IMREAD : public QObject
{
    Q_OBJECT
public:
    explicit IMREAD(QObject *parent = 0);

signals:

public slots:
    void IMREAD_Process();
private:
    bool Stop;
};
Run Code Online (Sandbox Code Playgroud)

imread.cpp

IMREAD::IMREAD(QObject *parent) :
    QObject(parent)
{
  this->Stop = false;
}

void IMREAD::IMREAD_Process()
{

  while(!Stop)
    {
          cv::Mat Image = CAM::Campture_F(25);//wait a maximum of 25 milisecond to grab a new frame
          if(Image.data())
            {
          FINAL_IM_VEC.push_back(Image);
            }
      }
    }

}
Run Code Online (Sandbox Code Playgroud)

imwrite.hpp

#ifndef IMWRITE_H
#define IMWRITE_H
#pragma once
#include <QObject>
class IMWRITE : public QObject
{
    Q_OBJECT
public:
    explicit IMWRITE(QObject *parent = 0);
signals:

public slots:
    void IMWrite_Process();
private:
    bool Stop;
};
Run Code Online (Sandbox Code Playgroud)

imwrite.cpp

IMWRITE::IMWRITE(QObject *parent) :
    QObject(parent)
{
  this->Stop =false;
}
void IMWRITE::IMWrite_Process()
{
    static int counter = 0;
    while(!Stop)
      {
        for(int i = 0 ; i < FINAL_IM_VEC.size() ; i++)
            {
                QString address = "/home/Provisioner/ThreadT/Results/" + QString::number(counter++) + ".jpg";
                cv::imwrite(address.toUtf8().constData(),FINAL_IM_VEC[i]);
                FINAL_IM_VEC.erase(FINAL_IM_VEC.begin() + i);
                i--;
            }
      }

}
Run Code Online (Sandbox Code Playgroud)

由于这只是整个项目的一部分,我已经删除了一些不相关的部分......但它显示了我如何在一张大图中编写我的多线程代码......所以如果有任何问题请通知我.

提前致谢.

use*_*906 5

让我们看看:2048*1080*3(通道数)*50 fps ~= 316MB/s,如果你用 raw 写图像。如果您使用的是 JPEG,根据压缩参数的不同,您可能会大幅减少,但如果是 1/5,您仍在向硬盘写入大量数据,特别是如果您在笔记本电脑上使用 5400rpm .

你可以做的事情:

  1. 正如 David Schwartz 所建议的,您应该使用队列和多线程。
  2. 如果您正在有效地编写图像序列,请改为保存视频。数据压缩得更多,写入磁盘的速度更快。
  3. 检查您当前设备的斑点并估计您可以写入的图像的最大大小。选择压缩参数以适应该大小约束。