Fast image averaging of Mono12p in C#

sleslo report abuse __ edited

M. Lentini from edmundoptics recommended your forum. I have a BaslerUsb: acA5472-17um on Win10-64 using C# (2019) using Mono12p I am working towards a fast image averaging routine to minimize image noise and illumination flicker. Would it be possible to collect the grabResults in a c# object for efficient averaging? A Mono12p Pixel is transported in as 1.5 bytes therefore setting the buffer as byte[] buffer = grabResult.PixelData as byte[]; confuses me. Averaging the bytes does not make sense to me because the byte-wise averages will not represent averaged gray values. This seems completely counterintuitive regular averaging on the bytes that are half from one and half from the other pixel has unintended consequences. It seems to make more sense to very early move the data into a jagged array of UInt16[][]. Which I have already accomplished. //in the capture routine fill the MyImageCollection[][] for example with 153 images. // After capture is finished and memory is nearly full // create a new AveragedBuffer[] by looping through myImages and average all 1st pixels to all last pixel into a final UInt16 [] that process could be improved with Parallel.For to use all cores. The part that I am most unclear about is how to turn the final UInt16 [] into a usable image.

My original approach was, saving e.g. 153 TIF and then outsourcing the image averaging in an ImageJ macro (Image Stack >>> Z-project)? The actual averaging is very fast but all the data transport and loading of the full FIJI program makes this approach very slow. Do you have any advice how to otherwise approach high performance image averaging after capturing with Streamgrabber? I was also looking into using EmguCV and Mat objects. But could not get that to be efficient either because it still relies on the saved TIFF or in the end I still rely on loops inside loops instead of doing efficient matrix math. And I still do not know how to perform further processing on the Mat. Is there a shortcut to turn a Basler GrabResultbuffer into a Mat directly? Do you have any ideas of what could work even better than these two half-baked approaches that both seem to have very steep learning curves. Thanks

I have found a snippet like this that seems to unpack a grab result buffer without nested loops. But my C# seems to not have the Marshal. keyword. ``` IntPtr p = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); image.GenImage1("byte", grabResult.Width, grabResult.Height, p);

Answers

T1000 report abuse __ edited

Dear Lentini,

pylon buffer can be directly attached to EmguCV if it is a 8 bit or 16bit.

8bit Pixelformat

Mat MatImageGray = new Mat((int)grabResult.Height, (int)grabResult.Width, DepthType.Cv8U, 1, grabResult.PixelDataPointer, grabResult.Width);

you need to use pylon image converter to convert Mono12p to Mono16 then you can attach it to Mat image.

// in case of Mono 12 or mono12p

                    converter.OutputPixelFormat = PixelType.Mono16;
                    byte[] buffer = new byte[converter.GetBufferSizeForConversion(grabResult)];
                    converter.Convert(buffer, grabResult);

                    GCHandle pinnedArray = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                    IntPtr pointer = pinnedArray.AddrOfPinnedObject();
                    Mat MatImageGray16 = new Mat((int)grabResult.Height, (int)grabResult.Width, DepthType.Cv16U, 1, pointer, grabResult.Width*2);
Comments
Jo-from-Imaginghub report abuse
Thank you for you help!
sleslo report abuse __ edited

I thought, I finally figured this out and this may help others!

Somewhere earlier you would need :

\<==== @T1000 how did you create the gray code block? PixelDataConverter converter = new PixelDataConverter(); { converter.OutputPixelFormat = PixelType.Mono16; }

It now runs to the final line of the code snippet:

Mat MatImageGray16 = new Mat((int)grabResult.Height, (int)grabResult.Width, DepthType.Cv16U, 1, pointer, grabResult.Width*2);

Here I get: e.Message = 'e.Message' threw an exception of type 'System.NullReferenceException'

I still do not know what is the difference between PixelType.Mono16 and DepthType.Cv16U, and DepthType CV_16U

I would appreciate, if someone could point me to a resource to make the learning curve less steep

Add Answer

Need support?

Just drop us an email to ... Show more