Hi,
I am experiencing an issue with my GenICam camera.
I encountered the following exception: “Native handle is not an IImageVPA type.” This error occurs on the line where I attempt to acquire an image using the stream.Wait(out status) method.
public void Test()
{
// discover devices
try
{
using (var devices = DeviceFactory.Discover(DiscoverFlags.IgnoreVins))
{
// open first device
using (var device = DeviceFactory.Open(devices[0], AcquisitionStack.GenTL))
{
// start streaming
var stream = ((GenICamDevice)device).GetStream<ImageStream>(0);
stream.Start();
// acquire data
WaitStatus status;
using (var image = stream.Wait(out status))
{
}
// stop streaming
stream.Abort();
}
}
}
catch (Exception ex)
{
}
}
Hi @Danv ,
what camera do you use?
When using ImageStream, you require the payload to be something, that is interpretable as a CVB Image.
You could allow a more generic representation of returned payloads if you use a CompositeStream:
class SimpleStreamingGen3
{
static void Main(string[] args)
{
using (var devices = DeviceFactory.Discover(DiscoverFlags.IgnoreVins))
{
using (var device = DeviceFactory.Open(devices[0], AcquisitionStack.GenTL))
{
var stream = ((GenICamDevice)device).GetStream<CompositeStream>(0);
stream.Start();
for (int i = 0; i < 10; i++)
{
WaitStatus status;
using (var composite = stream.Wait(out status))
{
using (var nodeMaps = NodeMapDictionary.FromComposite(composite))
{
Console.WriteLine($"Acquired image: {i}");
if (composite.Purpose == CompositePurpose.Image)
Console.WriteLine("is image");
else if (composite.Purpose == CompositePurpose.ImageList)
Console.WriteLine("is image list");
else if (composite.Purpose == CompositePurpose.MultiAoi)
Console.WriteLine("is multi aoi");
else if (composite.Purpose == CompositePurpose.RangeMap)
Console.WriteLine("is range map");
else if (composite.Purpose == CompositePurpose.PointCloud)
Console.WriteLine("is point cloud");
else if (composite.Purpose == CompositePurpose.ImageCube)
Console.WriteLine("is image cube");
else if (composite.Purpose == CompositePurpose.Custom)
Console.WriteLine("is custom");
else
Console.WriteLine("is something else");
}
}
}
stream.Abort();
}
}
}
}
I’m using a line scan hyperspectral camera that captures Mono16 frames with a resolution of 366x640 pixels (where the width represents physical pixels and the height represents spectral information per wavelength). After executing your code, I found that composite.Purpose is set to “custom.”
I’m looking for a way to directly access the image’s raw data using pointers or to copy the raw data into my own buffer. I attempted the following code:
The least you can expect, that is somehow interpretable would be a PFNCBuffer. Try to find it inside the composite. Then the last resort would be a Buffer.
Thanks for your help!
The following code worked for me:
var imageData = Stemmer.Cvb.Driver.Buffer.FromHandle(composite[0].Handle, Stemmer.Cvb.Runtime.InteropServices.ShareObject.No);
Marshal.Copy(imageData.BasePtr, _imageBuffer[curIdx], 0, imageSize);
One last question if you don’t mind!
How does the Stemmer.Cvb.Driver.Buffer.FromHandle function work? Does it copy the original data, or does it just return a pointer to the original data?
I’m trying to work with the BasePtr directly to avoid unnecessary copying. There might also be situations where I need to work on 2-3 images in parallel. Is it possible to use a FlowSetPool mechanism to hold the buffers I receive from Stemmer.Cvb.Driver.Buffer.FromHandle in a collection and release them when they’re no longer needed by calling the .Dispose() method?
Any advice about this?
FromHandle does return the pointer to the original data
In your case you are already copying the image data which is not necessary at all. You can use the existing managed flow set pool (if you configured it big enough) and wait for all images you want to process in parallel. Then you can access them. To be sure that the internal flows are disposed to be able to be used for the next images you either should use a using block or call dispose on the returned imageData.