I need to capture a frame from a webcam approximately 30 times per second. Essentially, I'm looking for a way to implement the following:
mainloop:
while( // scan is in process )
{
// process current image
// discard current image and dequeue next image (pop it off the front of the queue)
}
interrupt routine: // execute 30 times per second
{
// capture newImage with webcam
// enqueue newImage (push it onto the back of the queue)
// reset timer and return from interrupt
}
I'm afraid I don't have enough experience to know exactly what I'm looking for. If anybody has better advice about how to take a picture in the background every 30 seconds, I'd be thrilled to hear it. I'm new to OpenCV, although I have a fair amount of C++ experience in a classroom context. The end goal of my project is to use feature detection and matching in order to extract the frame-to-frame transformation matrix between every two frames (in other words, to track camera motion over a surface).
Target OS: OSX Yosemite 10.10.4, running XCode 6.3.1 * eventually this solution will be moved to a windows platform, so I'd love to find a solution that isn't platform-(or computer-)specific.
Most cameras capture images on their own clock. You are then a slave, not a master: you don't trigger image capture. Instead, you're notified whenever a new image is available. Any of the camera APIs (OpenCV, Qt Multimedia, etc.) will allow you to be notified when new camera data is available. If an API doesn't have asynchronous notification, you can spin a thread and perform the capture synchronously. Say, with OpenCV:
void process(const cv::Mat & frame) { ... }
int main() {
bool quit = false;
std::condition_variable queue_cv;
std::mutex queue_mutex;
std::deque<cv::Mat> queue;
auto capture = cv::VideoCapture(0);
// Worker thread - source of frames
auto thread = std::thread([&]{
int frame_count = 0;
while (! quit) {
cv::Mat frame;
if (! capture.read(frame)) break;
frame_count ++;
if (frame_count >= 30) {
std::unique_lock<std::mutex> lock(queue_mutex);
queue.push_back(frame);
lock.unlock();
queue_cv.notify_one();
frame_count = 0;
}
}
quit = true;
});
// Main thread - consumer of frames
while (!quit) {
std::unique_lock<std::mutex> lock(queue_mutex);
queue_cv.wait(queue_lock, []{ return queue.size() > 0; });
// we own the lock here
auto frame = queue.pop_front();
lock.unlock();
// lock is released, process the frame
process(frame);
}
thread.join();
}