CVB skips frames while storing consecutive images

Hi @keerthitheja ,

ok now that we figured that out I am pretty sure, that its not the network settings that are our problem here.
To understand what I think might be the issue I have to go back a bit.

:cvb: uses a buffer when acquiring images. This RingBuffer (consisting of storage to cover 3 of your images in length, width and number of planes) is created at the moment you load the camera in your application.
This is a good thread about the different ways to work with the Ringbuffer

Long story short, there are different ways to access this 3 Buffers but in any case, once your acquisition or framerate respectively, is faster than your processing (in your case saving the images) you will fill up your buffer up to the point you start losing frames.

The reason this happens is, that with the auto save consecutive images you write one single file every time. This has a (depending on the OS) more or less expensive overhead.
This feature is not designed for recording lots of image data in short time.

What you could do is right click on your camera and have a look if you can increase the buffercount or use the wrench/gear icon in the GenICamBrowser.
Warning: I dont know what the GenICam browser does if you stop acquisiton but still have pending buffers and auto save consecutive images enabled.
This would be something you could checkā€¦ please let me know about the answer :slight_smile:

If the GenICam browser checks for pending images and saves them after stopping an active grab, this would mean you just have to increase the number of buffers to a number that covers the time you want to record. You just have to be sure, that you have enough RAM for doing this.

Honestly, I am afraid this is a feature that is not implemented as it is not what you would typically do.

So there are three options I suggest from here on (assuming the increased amount of buffers dont do the trick either):

  1. Have a look at MovieInteractive2
    This tool saves images into a container, getting rid of the single file operations and boosting performance

  2. Write your own application using the 3rd generation acquisition stack, to have your own image buffer:
    3rd Gen Stack

  3. Check the following snippets using the .vin driver to perform 20 triggers on the camera (leaving you with 20 buffers filled) and processing them afterwards.
    You could do this for freerun as well, just make sure to have enought buffers.
    As I dont know which programming language you prefer I will cover C#, Py and C++ for you here:

C#:

using System; 
using System.Linq; 
using Stemmer.Cvb; 
using Stemmer.Cvb.Driver; 
using Stemmer.Cvb.GenApi;   

namespace RAMRecording 
{ 
  class Program 
  { 
    static void Main(string[] args) 
    { 
      Device device = DeviceFactory.Open("GenICam.vin"); 
      NodeMap deviceNodeMap = device.NodeMaps[NodeMapNames.Device];  

      Console.WriteLine($"Current RingBuffer amount: {device.Stream.RingBuffer.Count()}"); 
      device.Stream.RingBuffer.ChangeCount(20, DeviceUpdateMode.UpdateDeviceImage); 
      Console.WriteLine($"Changed RingBuffer amount to: {device.Stream.RingBuffer.Count()}");   

      var triggerMode = deviceNodeMap["TriggerMode"] as EnumerationNode; 
      var oldTriggerMode = deviceNodeMap["TriggerMode"] as EnumerationNode; 
      var triggerSource = deviceNodeMap["TriggerSource"] as EnumerationNode; 
      var oldTriggerSource = deviceNodeMap["TriggerSource"] as EnumerationNode; 
      var triggerSoftware = deviceNodeMap["TriggerSoftware"] as CommandNode;   

      triggerMode.Value = "On"; 
      triggerSource.Value = "Software";  

      Console.WriteLine("Starting stream and trigger camera given amount of times"); 
      device.Stream.Start();   

      // collect images to fill buffer 
      while(device.Stream.Statistics[StreamInfo.NumBuffersPending] < 20) 
      { 
        triggerSoftware.Execute(); 
      } 
      Console.WriteLine($"Currently locked buffers: {device.Stream.Statistics[StreamInfo.NumBuffersLocked]}"); 
      Console.WriteLine($"Currently pending buffers: {device.Stream.Statistics[StreamInfo.NumBuffersPending]}");   

      // process through images in buffer  
      while (device.Stream.Statistics[StreamInfo.NumBuffersPending] > 0)  
      { 
        using (var image = device.Stream.Wait()) 
        { 
          // Store your image somewhere
        } 
        Console.WriteLine($"NumBuffersPending: {device.Stream.Statistics[StreamInfo.NumBuffersPending]}"); 
      } 
      device.Stream.Stop();  

      // Reset changed settings of camera 
      device.Stream.RingBuffer.ChangeCount(3, DeviceUpdateMode.UpdateDeviceImage); 
      triggerMode.Value = oldTriggerMode.Value; 
      triggerSource.Value = oldTriggerSource.Value; 
    } 
  } 
} 

Py:

import cvb 
import os 
import cvb.foundation 
import sys   

device = cvb.DeviceFactory.open(os.path.join(cvb.install_path(), "drivers", "GenICam.vin")) 
deviceNodeMap = device.node_maps["Device"]   

deviceStream = device.stream() 
ringBufferCount = deviceStream.ring_buffer.count 
print("Current RingBuffer amount: " + str(ringBufferCount)) 

deviceStream.ring_buffer.change_count(20, 0) 
ringBufferCount = deviceStream.ring_buffer.count 
print("Changed RingBuffer amount to: " + str(ringBufferCount))   

triggerMode = deviceNodeMap["TriggerMode"] 
oldTriggerMode = deviceNodeMap["TriggerMode"] 
triggerSource = deviceNodeMap["TriggerSource"] 
oldTriggerSource = deviceNodeMap["TriggerSource"] 
triggerSoftware = deviceNodeMap["TriggerSoftware"] 
triggerMode.value = "On" 
triggerSource.value = "Software"  

print("Starting stream and trigger camera given amount of times") 
device.stream().start()  

# Collect images to fill buffer 
while(deviceStream.statistics[cvb.StreamInfo.NumBuffersPending] < 20): 
    triggerSoftware.execute() 
    print("Currently locked buffers: " + str(deviceStream.statistics[cvb.StreamInfo.NumBuffersLocked])) 
    print("Currently locked buffers: " + str(deviceStream.statistics[cvb.StreamInfo.NumBuffersPending]))
  

# Process through images in buffer 
while(deviceStream.statistics[cvb.StreamInfo.NumBuffersPending] > 0): 
    image = device.stream().wait() 
    print("NumBuffersPending: " + str(deviceStream.statistics[cvb.StreamInfo.NumBuffersPending])) 
device.stream().stop()   

# Reset changed settings of camera 
deviceStream.ring_buffer.change_count(3, 0) 
triggerMode = oldTriggerMode 
triggerSource = oldTriggerSource 

C++:

#include <iostream> 
#include <cvb/device_factory.hpp> 
#include <cvb/driver/stream.hpp> 
using namespace std; 
using namespace Cvb;   

int main() { 
auto device = DeviceFactory::Open(ExpandPath(InstallPath() + CVB_LIT("drivers/GenICam.vin")), AcquisitionStack::Vin); 
auto deviceNodeMap = device->NodeMap(CVB_LIT("Device")); 

cout << "Current RingBuffer amount: " << device->Stream()->RingBuffer()->Count() << endl; 
device->Stream()->RingBuffer()->ChangeCount(20, DeviceUpdateMode::UpdateDeviceImage); 
cout << "Changed RingBuffer amount to: " << device->Stream()->RingBuffer()->Count() << endl;  

auto triggerMode = deviceNodeMap->Node<EnumerationNode>("TriggerMode"); 
auto oldTriggerMode = deviceNodeMap->Node<EnumerationNode>("TriggerMode"); 
auto triggerSource = deviceNodeMap->Node<EnumerationNode>("TriggerSource"); 
auto oldTriggerSource = deviceNodeMap->Node<EnumerationNode>("TriggerSource"); 
auto triggerSoftware = deviceNodeMap->Node<CommandNode>("TriggerSoftware"); 
triggerMode->SetValue("On"); 
triggerSource->SetValue("Software");  

cout << "Starting stream and trigger camera given amount of times" << endl; 
device->Stream()->Start();   

/// Collect images to fill buffer 
while (device->Stream()->Statistics(StreamInfo::NumBuffersPending) < 20) { 
triggerSoftware->Execute(); 
}  

cout << "Currently locked buffers: " << device->Stream()->Statistics(StreamInfo::NumBuffersLocked) << endl; 
cout << "Currently pending buffers: " << device->Stream()->Statistics(StreamInfo::NumBuffersPending) << endl;   

// Process through images in buffer  
while (device->Stream()->Statistics(StreamInfo::NumBuffersPending) > 0) {  
device->Stream()->Wait(); 
//Save images here
cout << "NumBuffersPending: " << device->Stream()->Statistics(StreamInfo::NumBuffersPending) << endl; 
}   

device->Stream()->Stop();   

// Reset changed settings of camera 
device->Stream()->RingBuffer()->ChangeCount(3, DeviceUpdateMode::UpdateDeviceImage); 
triggerMode->SetValue(oldTriggerMode->Value()); 
triggerSource->SetValue(oldTriggerSource->Value()); 
} 

I hope this helps you find a solution for your usecase.

Cheers
Chris

1 Like