Hi @mave!
As @Chris pointed out, unsafe
is one of the key issues here. The keyword unsafe
allows coders to use pointers very much like they did in C or C++ in C#. unsafe
blocks are scoped - either by means of curly brackets {}
or through function scope. In your case I think function scope fits better: You’ll need to modify the function signature to
private unsafe void vpatbutton_Click(object sender, EventArgs e)
{
...
}
Note that you’ll need to enable unsafe code generation in your project (off by default…):
Without checking the highlighted box the use of the keyword unsafe
will result in a compiler error.
Please note that there is a conflict between the lines 147 and 167 in your code: pVPAT
has been declared as a Cvb.Image.VPAEntry
, but it should be a pointer to a VPAT entry for the code further down to make sense. Please also have a look at line 174 - I think what you intended to write was something like
pixelLabel.Text += (*(pImageLine + pVPAT[x].XEntry.ToInt64())).ToString() + " ";
I’d also want to warn about line 157 and 158. The plan here seems to be disabling the grab while the pixel value array is being copied and restart grab once that has been done (I guess that is what the variable grab
is going to be used for). Situations where such an approach is necessary certainly exist, but nevertheless I would like to point out two things:
- In :cvb: a lot of effort has been dedicated to making asynchronous acquisition available and easily accessible - Terminating image acquisition during processing will, however, eliminate the possibility of working on your image data while the next frame is being acquired and reduce the overall frame rate to
1/t
wheret
is the time taken by image processing plus the time taken for acquiring an image.
To make things worse, with some video interface drivers repetitively starting and stopping image acquisition incurs another performance hit: The GenICam.vin for example has a lot of things to kick off when starting image acquisition and several resources to free and threads to stop once acquisition stops. As a result, repetitively starting and stopping image acquisition will reduce the overall frame rate of your application significantly because the (non-neglegible) time taken for starting and stopping acquisition will have to be added tot
. - In your scenario, terminating acquisition to preserve the integrity of the currently processed image/VPAT is most likely unnecessary: Assuming that you are calling your routine from within an
ImageSnapped
event handler you can rely on the Image (and VPAT) to remain unaltered until the event handler has been exited (Image and VPAT internally are updated by the Image Control callingG2Wait
- which will not happen while theImageSnapped
event handler is being processed, unless the (nowadays hidden) Global Async Acquisition Enabled flag has been set).
And if you’re worried about the processing times: If the processing cannot keep up with the speed of image acquisition, the allocated number of buffers (default: 3) will be filled and once they are full any newly arriving images will simply be discarded (a fact that can be verified by invokingG2GetGrabStatus
with theG2INFO_NumBuffersLost
).
As for your question about processing speed:
- You are absolutely right in that
GetPixel
is terribly slow and unsuitable to retrieving the grey values of more than just a handful of pixels. - VPAT access is a lot faster than that and by and large the most versatile way of achieving what you want because it’ll work regardless of the actual VPAT configuration of your image(s).
- The linear access that @Chris mentioned is the fastest approach but is limited to images where you can rely on the pixel data to be linearly arranged in memory (which isn’t always the case - e.g. if you set the
RotateImage
flag in your driver’s *.ini file to any value other than 0 the pixel data will no longer be linearly arranged). For code snippets with linear access see for example this entry.