Problem with popNextImage and custom camera

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Problem with popNextImage and custom camera

Daniel Kovari
I've been working on a device adapter for Basler USB cameras and I'm having trouble properly setting up the circular buffer.
Overall the device adapter successfully communicates with Basler's API and returns images without causing micromanager to crash. However, if I call popNextImage() or popNextImageMD() via the CMMCore API (called from MATLAB, in my case) the getRemainingImageCount() counter never decreases. In otherwords, it appears that the images are stuck in the circular buffer queue.

I've tried to write the device adapter with as few overrides to the virtual functions defined in CCameraBase as possible. 

Pixel data is stored in a MicroManager ImageBuffer named img_, which is set during SnapImage()

Besides action interfaces and internal methods for communicating with Basler's API I've only implemented the following Methods:
//MM API - Image Properties
const unsigned char* GetImageBuffer(); // returns pointer to data in img_ 
long GetImageBufferSize() const; //size of data in img_
unsigned GetImageWidth() const; //get width of img_
unsigned GetImageHeight() const; //image height of img_
unsigned GetImageBytesPerPixel() const; //get bytes per pixel for img_
unsigned GetBitDepth() const; //bitdepth of img_

//MM API - Camera Interface
int Initialize(); //connect to Basler Pylon Library, setup camera
int Shutdown(); //shutdown camera, dissconnect from library
void GetName(char* name) const;
int SnapImage(); //locks imgLock_, calls camera.RetrieveResult(...), copies data to img_ buffer

In other words, I don't create a custom acquisition thread and don't re-define CCameraBase<>:InsertImage().

My code for SnapImage() is pretty simple:

int CPylonUSB::SnapImage() {
if (!_initialized) { return DEVICE_ERR; }
try {
MMThreadGuard g(imgLock_); //lock image
double timeout = max(SnapImageTimoutMS, max(camera.ExposureTime() / 250, 4 / camera.ResultingFrameRate()));
//grab image
Pylon::CGrabResultPtr ptrGrabResult;
camera.RetrieveResult(timeout, ptrGrabResult); //waits for the longest of {SnapTimeout, 4*Exposure time, 4*FrameRatePeriod}
//COPY DATA to buffer
img_.Resize(ptrGrabResult->GetWidth(), ptrGrabResult->GetHeight());
img_.SetPixels(ptrGrabResult->GetBuffer()); //copy data

catch (const GenericException &e) {
ostringstream os;
os << "Error in PylonUSB::SnapImage() : " << e.GetDescription() << endl;
return DEVICE_ERR;
return DEVICE_OK;

Is there something else I need to do so that the Circular Buffer is properly maintained?
Any advice or examples I should follow is appreciated.


Check out the vibrant tech community on one of the world's most
engaging tech sites,!
micro-manager-general mailing list
[hidden email]