3rd Generation Stack Simple Grabbing Program

I have a Genicam camera capturing Mono16 images 366X640 pixels.
I am trying to build a simple class/program using the 3rd Generation Stack that continuously grabs images and copies the image’s raw data into a buffer (byte array).
After that, I invoke the “New Image” event and the class subscribes processing it outside the Common Vision Blox environment.
The FPS I am working with is 230. (image every 4.3 ms).
The outside processing of every image takes ~2ms.

  1. Is RegisterManagedFlowSetPool needed in that case?
  2. Am I using the right way to copy the raw data into an array?
   image.Planes[0].TryGetLinearAccess(out LinearAccessData imageData);
   Marshal.Copy(imageData.BasePtr, _imageBuffers[index], 0, bufferSize);```
  1. Is running the grabbing function on a thread in a specific core or setting a processor affinity for better performance helpful/recommended?
  private void RunImageGrabbing(CancellationToken token)
        {
            double fps = 0;
            int index = 0;

            using (var devices = DeviceFactory.Discover(DiscoverFlags.IgnoreVins))
            {
                using (var device = DeviceFactory.Open(devices[0], AcquisitionStack.GenTL) as GenICamDevice)
                {
                    var stream = device.GetStream<ImageStream>(0);
                    stream.RegisterManagedFlowSetPool(100);

                    #region Initialize Buffer
                    int bufferSize = GetImageSize(device);
                    _imageBuffers = new byte[NumberOfBuffers][];
                    for (int i = 0; i < NumberOfBuffers; i++)
                        _imageBuffers[i] = new byte[bufferSize];
                    
                    #endregion

                    stream.Start();
                    Cvb.Utilities.TWStartStopWatch(m_Timer, 0);
                    while (grabbing && !token.IsCancellationRequested)
                    {
                       
                        using (var image = stream.Wait(token, out WaitStatus status))
                        {
                            if (status == WaitStatus.Ok && image != null)
                            {
                                image.Planes[0].TryGetLinearAccess(out LinearAccessData imageData);
                                Marshal.Copy(imageData.BasePtr, _imageBuffers[index], 0, bufferSize);
                                index = (index + 1) % NumberOfBuffers;

                                
                                // Calculate Current FPS
                                double dTimeMS;
                                Cvb.Utilities.TWReadStopWatch(m_Timer, 0, out dTimeMS);
                                fps = (1.0 / dTimeMS * 1000.0);
                                Console.WriteLine($"FPS {fps}");
                                Cvb.Utilities.TWStartStopWatch(m_Timer, 0);

                                //Event
                                OnNewImage?.Invoke(fps, _imageBuffers[index]);

                            }
                        }
                    }
                    stream.Abort(); 
                }
            }
        }

Hi @Danv , thanks for your request.

  1. There is a possiblity to register an user allocated memory space, conveniently. With RegisterExternalFlowSetPool() you don’t need to copy the Images into your buffer, but the driver does this, without further effort from you. Look here for a sample on that.
  2. gets unnecessary.
  3. There are stream handlers, that do this task asynchronously for you. Look here!

Hi @s-woe, thank you for your fast and detailed response.

I noticed that the external flow set pool is available only in C++. Is there an equivalent for C# API?

Excuse me, I totally ignored the fact that you’re on .NET. (Not on purpose)

No, there is no interface for that.

But, if you are willing to have an influence on the performance, timing and paralellism, I would strongly recommend to switch. Would that be feasible for you?

Otherwise, my personal experience with .NET is not really sufficient to help, but maybe @TStadler would have some valuable input?

Hello @Danv

as @s-woe said, unfortunately there is no way to directly stream images into user memory in C# (at least not currently).
As far as I can tell your code looks good to me.
Are you having performance issues or other problems?

If performance is an issue in your application and you know the amount of images you want to record, you could first record all images into the flow set pool and copy them to the array afterwards.

If you need the copying to happen live and you have performance issues, switching to C++ could be an option, but I would only recommend that once we have exhausted every other possibility.

But without any additional context your code looks fine to me.

Cheers,
Tim

1 Like