As you say, you can't trigger them at the exact same time without hardware capable of doing so. Some IMU's supply an external trigger pin, and I see no reason why you couldn't buy cameras that have a trigger pin.
Sure, your suggestion of using two threads and triggering them both at the same time that way would work, so long as you can send messages to both threads at the same time. Unfortunately, you cannot send messages to two threads at the exact same time, and you cannot ensure the processor is running those threads (the OS has thousands of threads it has to run) so you'll have to settle for a very small time difference between them. You'll also end up with all the normal multi-thread communication issues.....
Fortunately, there is a simpler solution. OpenCV provides multiple different ways to get images from a camera. The normal one is to use the function read()
. This function actually does multiple things. First it tells the camera to start taking a photo. Then it waits until the camera has taken the photo, and finally, it reads the photo back. This whole process takes multiple milliseconds (on a 30FPS camera it takes ~32ms, on a 60FPS camera it takes ~17ms). You can drastically reduce this time by using the functions grab()
and retrieve()
. Grab tells the camera to take the photo, and retrieve waits for the camera and gets the data. So if you do (pseudo-code):
cam1.grab() # very fast
cam2.grab() # also very fast
img1 = cam1.retrieve() # slow because it has to wait for the camera
img2 = cam2.retrieve() # fast because when cam1 has finished, cam2 probably has as well
Using this method you can retrieve the images from both cameras at the framerate of the cameras. This method is mentioned briefly in the opencv documentation where it says:
The primary use of the function [note: the grab() function] is in multi-camera environments,
especially when the cameras do not have hardware synchronization. That
is, you call VideoCapture::grab() for each camera and after that call
the slower method VideoCapture::retrieve() to decode and get frame
from each camera. This way the overhead on demosaicing or motion jpeg
decompression etc. is eliminated and the retrieved frames from
different cameras will be closer in time