09-23-2009 09:31 PM
09-24-2009 08:38 AM
I have found an answer to my first question in of all places the NI-IMAQ User Manual (http://www.ni.com/pdf/manuals/370160d.pdf). I've been so used to trusting the Function Reference for everything I forgot the user manual had useful information.
According to the manual FRAME_START "... becomes TRUE when the device detects the first valid pixel in the current region of interest." If I have a ROI that starts other than (0,0) there would be some delay but it seems FRAME_START is the best I can get.
Any ideas on this? I would imagine this is a very common scenario of timestamping frames, but perhaps I'm mistaken.
09-24-2009 08:19 PM
Hi Joshuadoe,
Have you taken a look at some of the suggestions here or here? I realize that you are using C and Cameralink but some of the concepts can be brought over (a lot of the functions in labVIEW have a similar name in C).
Timestamping isn't rare but usually it's based off of a trigger or the time is already part of the metadata coming from the camera.
09-26-2009 09:59 AM
Thanks O54E,
I saw that first post but didn't read too carefully as I wasn't using LabVIEW. I read it again and what it suggests is basically what I tried doing yesterday, but using a loop versus a callback (which I presume can't be done in LabVIEW). I install an asynchronous callback on the FRAME_START signal and in the callback query ATTR_IMG_FRAME_COUNT. The callback should be called when frame N (zero based) is being acquired, but since it is not acquired yet the frame count should also be N (one based). I tried this with two cameras and then tried synchronizing them later. I was able to do this but there was approximately a 7 frame difference between what the timestamps and the image itself indicated. I'm not so much interested in the exact time any particular frame was acquired, but ensuring that two images at t=0s were taken at the same moment as well as at t=100s. If this frame offset is consistent then I have already achieved my objective.
Any further comments on this? I've pasted a code snippet below to pass along the way I'm doing this.
void IMAQClass::thread() { int ret; uInt32 *bufAddr=0, reqBufNum = 0, curBufNum=0; // register callback and start acquisition ret = imgSessionWaitSignalAsync2(m_sId, IMG_SIGNAL_STATUS, IMG_FRAME_START, IMG_SIGNAL_STATE_RISING, ImaqCallback, this); ret = imgSessionStartAcquisition(m_sId); while(!m_stopRequested) { // write timestamp and image to disk ret=imgSessionExamineBuffer2(m_sId, reqBufNum, &curBufNum, (void**)&bufAddr); m_file->write(m_timestamps[curBufNum],1,23); m_file->write(bufAddr,1,m_info.imageSize); ret = imgSessionReleaseBuffer(m_sId); reqBufNum = curBufNum+1; } imgSessionStopAcquisition(m_sId); } uInt32 ImaqCallback(SESSION_ID sid, IMG_ERR err, IMG_SIGNAL_TYPE signalType, uInt32 signalIdentifier, void* userdata) { static uInt32 val; if(signalIdentifier==IMG_FRAME_START) { imgGetAttribute(m_sId, IMG_ATTR_FRAME_COUNT, &val); m_timestamps[val] = to_iso_string(t); } return 1; // rearm callback }