2016-06-01 3 views
-1

Я хочу построить набор данных лица. Поэтому я пишу программу grabber с (Visual C++), которая захватывает цвет/глубину/инфракрасный порт и некоторые другие данные из kinect для Windows со скоростью 60 кадров в секунду, а затем сохраняет их на жестком диске. это занимает много времени, поэтому я не могу сэкономить более 10 кадров в секунду, и многие кадры будут удалены. Я пытаюсь использовать fileStorage (opencv) для сохранения данных yaml, но это слишком медленно. Я думаю об использовании двух потоков, один для захвата данных, а другой для сохранения. но передача данных между двумя независимыми потоками является основной проблемой. Какое лучшее решение для сохранения данных без потери кадров?написать данные быстрого kinect на жестком диске

+1

вычислить необходимую ширину полосы частот (60fps * sizeOfAFrame) и сравнить его с вашим оборудованием писать пропускной способности. Если вы теоретически МОЖЕТ писать все кадры, вы можете оптимизировать их путем кеширования, а затем писать из другого потока. Я видел файловые системы, где через несколько секунд произошла какая-то задержка, которая была зафиксирована многопоточными. Запись с файловым хранилищем, вероятно, намного медленнее, чем запись необработанных данных, поскольку размер данных, по-видимому, резко возрастает, и вам нужно дополнительное время для форматирования/преобразования. – Micka

+0

OP: Вы уверены в 60 FPS? Из того, что я могу найти, это 30. Тем не менее, изображение RGB с разрешением 1920x1080 составляет 6075 KiB, глубина 16 бит и ИК на 512x424 составляет 424 KiB каждый -> 6923 KiB за кадр при 30 Гц дает ~ 203 ми/с. Как говорит Мика, зависит от вашего оборудования. Вы должны обязательно писать необработанные данные, вы вряд ли сможете сжать это где-нибудь близко к реальному времени (по крайней мере, не только с процессором). Покажите некоторый код и предоставьте более подробную информацию о HW и сколько вы хотите сохранить (время - длина одной непрерывной последовательности кадров). –

ответ

-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 (интермедиат ARGC, _TCHAR * ARGV []) {

thread GrabberThread(GrabberThreadFunc); 
thread SaverThread(SaverThreadFunc); 

if (GrabberThread.joinable()) 
    GrabberThread.join(); 

if (SaverThread.joinable()) 
    SaverThread.join(); 

return 0; 

}

+0

R.y.z, не могли бы вы поделиться своим решением? – Geucimar

-1

Кэширование 60 или более кадров в памяти через mmap() и использование 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.

Теперь, если Atomic operations library используется для JOB::valid, тогда вы можете легко избежать взаимной блокировки для синхронизации.

Затем Grabber должен просто найти элемент в векторе (пройдя через все элементы), который имеет JOB::valid==0 и сохранит фрейм в этом конкретном элементе.

Similary, FileSavingThread должен найти элемент в векторе с JOB::valid==1 и сохранить фрейм, указанный в этом элементе в файл.

В зависимости от производительности вы можете попытаться увеличить количество элементов в векторе или увеличить количество файлов FileSavingThread или обоих.

//-------------------------------------------------------------------------

  • Новый метод 2: Использование существующего файла, который памяти Подключенные.
  • Ссылка: Memory Mapped File

Здесь, если мы знаем, сколько кадров или сколько данных, соответствующих числу временных секунд должны быть сохранены, то мы можем создать файл этого большого размера, прежде чем руки и памяти карты этот файл. Тогда сохранение кадров будет таким же простым, как запись в память смежным образом. Кэширование и ввод-вывод будут автоматически управляться ОС оптимальным образом.

Это возможно, потому что все параметры w.r.t кадров, участвующих в вычислении, фиксированы.

Чтение кадров также может быть выполнено с помощью карты памяти. Сохранение сохраненного файла. Если требуется один кадр, то вычисление смещения от начала сохраненного файла легко подсчитать, поскольку все параметры, необходимые для вычисления смещения определенного кадра, являются фиксированными.

Теперь, какие преимущества есть при чтении/записи таким образом, можно прочитать здесь What Do Memory-Mapped Files Have to Offer?

+1

К сожалению, вам нужен мьютекс на 'std :: vector', использование атомной библиотеки на члене вектора не помогает. Когда Grabber добавляет задание в вектор, он может перераспределять, который ** перемещает ** все существующие задания и их атомные переменные. Поэтому FileSavingThread необходимо блокировать вектор во время его чтения. – MSalters

+0

Visual Studio подразумевает Windows - в Windows нет 'senfile()'. Картирование памяти также использует другой API, а не 'mmap()'. Вы должны объяснить использование mmap более подробно (похоже, вы хотите использовать анонимную общую память, но это не очевидно). Синхронизация не является тривиальной проблемой, был бы полезен конкретный пример, по крайней мере, с некоторым псевдокодом или ссылками на соответствующие ответы. Общая идея неплохая, но ответ может быть намного более подробным. –

+0

@MSalters: Если вы внимательно прочитали ответ, вы найдете строку «вектор с предопределенным количеством элементов». Таким образом, нет возможности перераспределения или даже добавления нового элемента в вектор, который потребует блокировки. Я уже дал хотя бы по вопросу, который вы упомянули. Кроме того, Grabber сделает 'JOB: valid = 1' после заполнения данных в' JOB :: buf', пока FileSavingThread не найдет 'JOB: valid == 0'. И так как атомарная операция (TestAndSet()) используется для установки «JOB: valid», поэтому на самом деле нет необходимости блокировать синхронизацию. – sameerkn

Смежные вопросы