我想构建一个face数据集。所以我用(Visual c ++)编写一个抓取程序,用60 fps从kinect中获取颜色/深度/红外和其他一些数据,然后将它们保存在硬盘上。它需要花费很多时间,因此我不能在一秒钟内保存超过10帧,并且丢弃了大量帧。我尝试使用fileStorage(opencv)将数据保存为yaml,但它也很慢。我正在考虑使用两个线程,一个用于获取数据,另一个用于保存。但两个独立线程之间的数据通信是主要问题。 在不丢失框架的情况下保存数据的最佳解决方案是什么?
答案 0 :(得分:-1)
通过mmap()
缓存内存中的60个或更多帧,并使用sendfile
保存文件。当然,在缓存和保存之间需要一些同步。
假设您使用具有预定义数量的元素的vector<JOB>
,例如600(60 * number_of_sec_which_are_cached)。
struct JOB
{
int second_number; //second related to time
int frame_number; //frame number in second specified by "JOB::second_number"
unsigned char *buf; //frame buffer
unsigned int buf_length; //number of bytes in frame which would be a fixed number.
int valid;
};
Grabber将在获取框架时JOB::valid = 1
。
FileSavingThread将使用JOB::valid
来确定框架是否已准备好保存JOB::valid==1
,保存后将JOB::valid=0
。
现在,如果JOB::valid
用于JOB::valid==0
,那么您可以轻松避免使用互斥锁进行同步。
然后,Grabber必须在向量中找到一个元素(通过遍历所有元素),其中JOB::valid==1
将该帧存储在该特定元素中。
类似地,FileSavingThread必须在向量中找到一个具有//-------------------------------------------------------------------------
的元素,并将该元素中指定的帧存储到文件中。
根据性能,您可以尝试增加向量中的元素数量或增加FileSavingThread的数量或两者。
{{1}}
在这里,如果我们知道有多少帧或者与保存的时间秒数相对应的数据,那么我们可以在手和内存映射该文件之前创建一个这么大的文件。然后,保存帧将像以连续方式写入存储器一样简单。操作系统将以最佳方式自动管理缓存和I / O.
这是可能的,因为计算中涉及的所有参数w.r.t都是固定的。
也可以通过Memory Mapping保存文件来读取帧。如果再次需要单个帧,则从保存文件的开始计算偏移量很容易计算,因为计算特定帧的偏移量所需的所有参数都是固定的。
现在可以在这里阅读以这种方式阅读/写作的好处Memory Mapped File
答案 1 :(得分:-1)
感谢您的帮助。 我通过定义两个线程,共享内存(队列)和互斥锁来解决问题。
//I have a passenger class that store all data including images in it
#include "passenger.h"
//I define a queue from passenger class
queue<passenger> passengerQueue;
//and a mutex
std::mutex myMutex;
void GrabberThreadFunc()
{
//get the data and store it in a passenger object
if (nearPassenger.valid)
{
std::lock_guard<std::mutex> guard(myMutex);
passengerQueue.push(nearPassenger);
}
}
void SavetThreadFunc()
{
if (!passengerQueue.empty())
{
std::lock_guard<std::mutex> guard(myMutex);
passengerQueue.front().SaveData();
passengerQueue.pop();
}
}
int _tmain(int argc,_TCHAR * argv []) {
thread GrabberThread(GrabberThreadFunc);
thread SaverThread(SaverThreadFunc);
if (GrabberThread.joinable())
GrabberThread.join();
if (SaverThread.joinable())
SaverThread.join();
return 0;
}