Сохранение изображений через шаблон производитель-потребитель с использованием BlockingCollection.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Сохранение изображений через шаблон производитель-потребитель с использованием BlockingCollection.

Сообщение Anonymous »

Я столкнулся с проблемой между производителем и потребителем: у меня есть камера, которая очень быстро отправляет изображения, и мне приходится сохранять их на диск. Изображения имеют формат ushort[]. Камера всегда переопределяет одну и ту же переменную типа ushort[].
Поэтому между одним захватом данных мне приходится копировать массив и, если возможно, сохранять его, чтобы освободить вспомнить этот образ. Важно не потерять ни одного изображения с камеры, даже если для этого придется увеличить используемую память: вполне допустимо, что потребитель (сохранение изображений с освобождением памяти) работает медленнее, чем производитель; однако недопустимо не скопировать изображение в память вовремя.
Я написал пример кода, который должен имитировать проблему:
  • Код: Выделить всё

    image_ushort
    : изображение, созданное камерой, которое необходимо скопировать в BlockingCollection до поступления следующего изображения
  • Код: Выделить всё

    producerTask
    : имеет цикл, который должен имитировать поступление изображения каждый раз_wait; за это время производитель должен скопировать изображение в BlockingCollection.
  • Код: Выделить всё

    consumerTask
    : должен работать с BlockingCollection, сохраняя изображения на диск и тем самым освобождая память; не имеет значения, работает ли потребитель медленнее, чем производитель.
Я поставил time_wait равным 1 миллисекунде, чтобы проверить производительность ( на самом деле камера не сможет достичь такой скорости). Времена соблюдаются (с максимальной задержкой 1-2 мс, поэтому допустимо), если в коде нет сохранения на диск (комментарий image1.ImWrite(имя_файла)). Но при включенном сохранении на диск вместо этого я получаю задержки, которые иногда превышают 100 мс.
Вот мой код:

Код: Выделить всё

private void Execute_test_producer_consumer1()
{
//Images are stored as ushort array, so we create a BlockingCollection
//to keep images when they arrive from camera
BlockingCollection imglist = new BlockingCollection();

string lod_date = "";

/*producerTask simulates a camera that returns an image every time_wait
milliseconds.  The image is copied and inserted in the BlockingCollection
to be then saved on disk in the consumerTask*/
Task producerTask = Task.Factory.StartNew(() =>
{
//Number of images to process
int num_img = 3000;
//Time between one image and the next
long time_wait = 1;

//Time log variables
var watch1 = System.Diagnostics.Stopwatch.StartNew();
long watch_log = 0;
long delta_time = 0;
long timer1 = 0;
List timer_delta_log = new List();
List timer_delta_log_time = new List();

int ii = 0;

Console.WriteLine("-----START producer");

watch1.Restart();

//Here I expect every wait_time (or a little more) an image will be inserted
//into imglist

while (ii < num_img)
{
timer1 = watch1.ElapsedMilliseconds;
delta_time = timer1 - watch_log;

if (delta_time >= time_wait || ii == 0)
{
//Add image
imglist.Add((ushort[])image_ushort.Clone());

//Inserting data for time log
timer_delta_log.Add(delta_time);
timer_delta_log_time.Add(timer1);
watch_log = timer1;
ii++;
}
}

imglist.CompleteAdding();
watch1.Stop();

lod_date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
Console.WriteLine("-----END producer: " + lod_date);

// We only print images that are not inserted on schedule

int gg = 0;
foreach (long timer_delta_log_t in timer_delta_log)
{
if (timer_delta_log_t > time_wait)
{
Console.WriteLine("-- Image " + (gg + 1) + ", delta: "
+ timer_delta_log_t + ", time: " + timer_delta_log_time[gg]);
}
gg++;
}
});

Task consumerTask = Task.Factory.StartNew(() =>
{
string file_name = "";
int yy = 0;

// saving images and removing data
foreach (ushort[] imm in imglist.GetConsumingEnumerable())
{
file_name = @"output/" + yy + ".png";
Mat image1 = new Mat(row, col, MatType.CV_16UC1, imm);

//By commenting on this line, the timing of the producer is respected
image1.ImWrite(file_name);
image1.Dispose();
yy++;
}

imglist.Dispose();

lod_date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
Console.WriteLine("-----END consumer: " + lod_date);
});
}
Я также подумал, что BlockingCollection может оставаться заблокированным на протяжении всего цикла foreach и, следовательно, сохранения изображения на диск. Поэтому я также попробовал заменить foreach на это:

Код: Выделить всё

while(!imglist.IsCompleted)
{
ushort[] elem = imglist.Take();
file_name = @"output/" + yy + ".png";
Mat image1 = new Mat(row, col, MatType.CV_16UC1, elem);

//By commenting on this line, the timing of the producer is respected
image1.ImWrite(file_name);
image1.Dispose();
yy++;
}
Но результат не меняется.
Что я делаю не так?

Подробнее здесь: https://stackoverflow.com/questions/709 ... collection
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»