PDA

View Full Version : snapImages() does not capture what the camera is seeing at the time.



kojih_hatanaka
July 18, 2014, 03:45:16
Hello,

I am developing a system which project images on a wall and capture it with the camera, DFK23U618.
The sequence is:
(1) Create a sink, set parameters, then DShowLib::Grabber::startLive()
(2) Project an image
(3) Capture it with DShowLib::FrameHandlerSink::snapImages(1), and save the image with save() method.
(4) Repeat (2)-(3)
(5) DShowLib::Grabber::stopLive()

I have noticed that the snapImages(1) function does not fill the buffer with the image what the camera is seeing at the time, but a a little past image. Even I trace the code and confirmed the expected image is really projected, then call snamImages(), the saved image with save() function produces different image.

It looks like, the camera device holds images in buffers and snap images uses the one filled earlier than the time snapImage called. How can I capture exactly current view of the camera?


I have tried DShowLib::Grabber::prepareLive() instead of startLive() and do:
startLive()
snapImages(1)
suspendLive()

every snap, but it does not resolve the issue.

I also tried to capture multiple images at once like snapImages(5) and take only one image with getLastAcqMemBuffer() method. It works, but takes longer time than single shot of course. Requerement of the system is to perform 30fps at least and it can't be met with this way.

I need expert's help on this issue.

Thank you,
Koji Hatanaka

Stefan Geissler
July 18, 2014, 09:37:41
Hello Koji Hatanaka

snapImages() grabs an image from the live stream sent by the camera. Therefore, you always have a small delay between snapImages call and the image delivery.
Also your sequence is very time consuming. Especially the startLive() call needs some time for the preparation of the camera, color space transfoormation setup etc.
Therefore, you should create the sink and prepare the grabber somewhere at program start. There is a function "prepareLive()" that can do this. It will not start the live stream but prepare all the internal stuff. With "suspendlive()" instead of "stoplive" the live stream is stopped, but the internal stuff is kept.
Then the call to startlive() and snapimages() is much faster.

However, if you really want the image at a special point of time, you should trigger the camera. You can do this either by hardware or by software.


sink->snapMode(false)
grabber.startLive();
grabber.setExternalTrigger(true);


You also should use a grabber listener inherited class to establish a callback, that is called, when the image arrives.


CListener cListener = new CListener();
grabber.addListener( 6cListener, GrabberListener::eFRAMEREADY|
GrabberListener::eOVERLAYCALLBACK );

It's frameReady() function is called, when the image arrives.

Last step: Do a software trigger. First a function, that queries the software trigger:



void Push_Trigger_Software_Trigger(Grabber* pGrabber)
{
if( pGrabber->isDevValid() )
{
tIVCDButtonPropertyPtr pButtonItf;
tIVCDPropertyItemsPtr pItems = pGrabber->getAvailableVCDProperties();
pItems->findInterfacePtr(VCDID_TriggerMode, VCDElement_SoftwareTrigger ,pButtonItf);

if( pButtonItf != NULL )
{
pButtonItf->push();
}
}
}


It is called as



Push_Trigger_Software_Trigger(&grabber);


Then the camera starts to expose the image and send it to your computer. The only disadvantage of this method is you do not see a live video.

kojih_hatanaka
August 3, 2014, 16:20:46
Thank you for your reply.

The way you instructed, which uses frame ready callback and software trigger, almost resolved the issue.

There is still timing issue remained. As you described, there is some delay and the code in frame ready callback can access image a little BEFORE push of the software trigger.

Since my scenario is to capture an image which projector is displaying, I added short sleep() after the image displayed and before push() of the software trigger. It works, but takes extra time to take a picture. I can't figure out how much time I have to wait and therefore I have to add enough wait with margin. It is ineffective.

I wonder if there is (1) a method to clear remaining capture buffer to ensure capturing images AFTER the software trigger pushed and (2) a way to let the device or class library only if an image ready which is captured AFTER the software trigger pushed with minimum required delay.

Thanks

Stefan Geissler
August 4, 2014, 08:49:33
Hello


little BEFORE push of the software trigger.

Are you sure about this? The software trigger function sends the trigger command to the camera immediately and returns with 4~7ms. The camera started to expose the image with the set exposure time and sends the image out to the computer within the frame rates time intervall. Exposure time and image delivery add up for most cameras. That means, if you exposure with 1/100 sec exposure time at e.g. 60 fps, the image will be in the frameready call after 10 + 16.66 ms + a few ms for colorspace transformation. This is at least 26.66ms with is longer than the software trigger call needs.

Therefore, you may see an older image or you did not enable the trigger for your camera.

kojih_hatanaka
August 5, 2014, 08:50:23
> little BEFORE push of the software trigger.
Are you sure about this?

I'm afraid I believe so. At least, I have my program to wait projection of an image finished, then start software trigger. The frame ready event callback is called with FrameNumber 1, but the captured image in the buffer shows a little before the projected image ready.

Honestly, I don't have enough facility to double check. I am relying on that Windows API 'UpdateWindow()' ensures redraw completed when it returns. It would be really appreciated it if Imaging Control could investigate if there is no issue in the C++ class lib, or there is no possibility of this situation happens.

Best regards,
Koji Hatanaka

Stefan Geissler
August 5, 2014, 09:25:13
Hello

I would like to check the sequence:
Camera trigger is true.

1) Receive an image for the next software trigger coming in future
2) Push software trigger for the image already received

This sounds a little bit weird. So there must be a misunderstanding from my side.

I would like you to create a support request at http://www.imagingcontrol.com/en_US/support/case/. So you can send me a small project showing the issue so I can debug