How I grab from IP cameras

I’ve seen some questions about how to grab frames from IP cameras, I do it using OpenCV (needs to be installed and set) and ofxCv, which wraps its own Mat as an ofImage, that way we just need to read into a cv::Mat and the ofImage that points to those pixels can just update and render.

I use an ofThread to grab the frames in the background, this is very efficient. Although, something tells me this isn’t the best approach. I am trying to make it work in another project without success. It works in an empty example using this code.

grabber.h

  
#pragma once  
#include "ofMain.h"  
#include "ofxCv.h"  
#include <opencv/cv.h>  
#include <opencv/highgui.h>  
#include <opencv2/core/core.hpp>  
  
class grabber : public ofThread  
{  
public:  
	grabber(string ,string, string, ofImage &);  
	void threadedFunction();  
	~grabber(void);  
	bool imageReady;  
  
private:  
	cv::VideoCapture vcap;  
	cv::Mat auxMat;  
	cv::Mat matFrame;  
};  
  

grabber.cpp

  
#include "grabber.h"  
  
  
grabber::grabber(string usr, string pwd, string ip, ofImage & image)  
{  
	if(! vcap.open( "[http://"+usr+":"+pwd+"@"+ip+"/axis-cgi/mjpg/video.cgi?resolution=1920x1080&.mjpg"](http://"+usr+":"+pwd+"@"+ip+"/axis-cgi/mjpg/video.cgi?resolution=1920x1080&.mjpg") ))  
		std::cerr << "Error opening camera "<< ip << std::endl;  
	image.allocate(1920,1080,OF_IMAGE_COLOR);  
	while(!vcap.read(matFrame));  
	ofxCv::toOf(matFrame,image);  
	imageReady = false;  
}  
  
void grabber::threadedFunction(){  
	while(isThreadRunning()){  
		vcap.read(matFrame);  
		imageReady = true;  
	}  
}  
  
grabber::~grabber(void)  
{  
}  
  
  

And in testApp.h:

  
  
//...  
ofImage frame;  
grabber * myThread;  
//...  
  

testApp.cpp:

  
  
void testApp::setup(){  
	  
	myThread = new grabber("user","pwd","xxx.xxx.xxx.xxx", frame);  
	myThread->startThread(true,false);  
}  
  
void testApp::update(){  
	if(myThread->imageReady){ // no need to lock as it's a bool ?, it works  
		frame.update();  
		myThread->imageReady = false;  
	}  
}  
  
void testApp::draw(){  
	frame.draw(0,0);  
}  
  

Is there anything wrong with this approach? Given that I just want ofImages to render video, I guess there is no problem making it share memory with the cv::Mat… but I could use more experienced eyes on this.

hi chuckleplant,
i’m trying something similar, but first without a thread. I’m getting linker errors “Undefined symbols for architecture i386:” for all of the cv:VideoCapture functions. I’m on osx 10.8.5, oF 0.8.0, xcode 5.

Have you tried to compile this under those conditions? if so, did you get the same linker errors? Thanks,
Jake

i’ve asked a similar question here.

Hi, I was using 0.7.4 and it had some issues with cv::VideoCapture if you used the opencv libs that came with OF. I think it was something about ffmpeg on opencv 231. I think this was it.
I installed opencv 2.4.6 at that time and used those binaries instead. Again, this was done on Windows and OF 074.

Hope this helps

Thanks @chuckleplant. I’m a bit frightened of trying to use my own build of OpenCV. That being said, I solved my problem and I’m suing ofxIpVideoGrabber to pull in video and use if with ofxCv. My issue is that the RunningBackground::update function expects a three or four channel image, and i was converting to grayscale before sending it. I’m going to explain better in my original post. Thanks very much for your help.