I am working on reducing the image capturing time for pi camera module ..and I found out a way of capturing the image within 10 ms using a c++ API
This the my main program from where I try to capture an image
class Timer
{
private:
struct timeval _start, _end;
public:
Timer()
{
}
void start()
{
gettimeofday(&_start, NULL);
}
void end()
{
gettimeofday(&_end, NULL);
}
double getSecs()
{
return double(((_end.tv_sec - _start.tv_sec) * 1000 + (_end.tv_usec - _start.tv_usec)/1000.0) + 0.5)/1000.0;
}
};
raspicam::RaspiCam_Still_Cv Camera;
//Returns the value of a param. If not present, returns the defvalue
float getParamVal ( string id,int argc,char **argv,float defvalue )
{
for ( int i=0; i<argc; i++)
if ( id== argv[i] )
return atof ( argv[i+1] );
return defvalue;
}
//prints program command line usage
void usage()
{
cout<<"-w val : sets image width (2592 default)"<<endl;
cout<<"-h val : sets image height (1944 default)"<<endl;
//cout<<"-iso val: set iso [100,800] (400 default)"<<endl;
}
int main ( int argc, char *argv[])
{
usage();
Timer timer;
int width = getParamVal ( "-w",argc,argv,750 );//define width
int height =getParamVal ( "-h",argc,argv,150 );//define height
cout << "Initializing ..."<<width<<"x"<<height<<endl;
Camera.set ( CV_CAP_PROP_FRAME_WIDTH, width );
Camera.set ( CV_CAP_PROP_FRAME_HEIGHT, height );
Camera.open();
cv::Mat image;
cout<<"capturing"<<endl;
timer.start();
if (!Camera.grab())
{
cerr<<"Error in grab"<<endl;
return -1;
}
Camera.retrieve ( image );
timer.end();
cerr<< timer.getSecs()<< " seconds for "<<endl;
cout<<"saving picture.jpg"<<endl;
cv::imwrite ( "picture.jpg",image );
return 0;
}
raspicam::RaspiCam_Still_Cv Camera;
//Returns the value of a param. If not present, returns the defvalue
float getParamVal ( string id,int argc,char **argv,float defvalue )
{
for ( int i=0; i<argc; i++ )
if ( id== argv[i] )
return atof ( argv[i+1] );
return defvalue;
}
//prints program command line usage
void usage()
{
cout<<"-w val : sets image width (2592 default)"<<endl;
cout<<"-h val : sets image height (1944 default)"<<endl;
// cout<<"-iso val: set iso [100,800] (400 default)"<<endl;
}
int main (int argc, char *argv[])
{
usage();
Timer timer;
int width = getParamVal ( "-w",argc,argv,750 );//define width
int height =getParamVal ( "-h",argc,argv,150 );//define height
cout << "Initializing ..."<<width<<"x"<<height<<endl;
Camera.set ( CV_CAP_PROP_FRAME_WIDTH, width );
Camera.set ( CV_CAP_PROP_FRAME_HEIGHT, height );
Camera.open();
cv::Mat image;
cout<<"capturing"<<endl;
timer.start();
if (!Camera.grab())
{
cerr<<"Error in grab"<<endl;
return -1;
}
Camera.retrieve ( image );
timer.end();
cerr<< timer.getSecs()<< " seconds for "<<endl;
cout<<"saving picture.jpg"<<endl;
cv::imwrite ( "picture.jpg",image );
return 0;
}
the grab function is present in a cpp file raspicam_still_cv.cpp while in turn calls another function called takepicture from private_still_impl.cpp
grab function
bool RaspiCam_Still_Cv::grab ()
{
if ( image_buffer==0 )
image_buffer=new uchar [ _impl-> getImageBufferSize()];
_isGrabbed= _impl->takePicture ( image_buffer, _impl-> getImageBufferSize() );
return _isGrabbed;
}
take picture function from private_still_imapl.cpp
bool Private_Impl_Still::takePicture ( unsigned char * preallocated_data, unsigned int length )
{
initialize();
int ret = 0;
sem_t mutex;
struct timeval t0;
struct timeval t1;
float elapsed;
sem_init ( &mutex, 0, 0 );
RASPICAM_USERDATA * userdata = new RASPICAM_USERDATA();
userdata->cameraBoard = this;
userdata->encoderPool = encoder_pool;
userdata->mutex = &mutex;
userdata->data = preallocated_data;
userdata->bufferPosition = 0;
userdata->offset = 0;
userdata->startingOffset = 0;
userdata->length = length;
userdata->imageCallback = NULL;
encoder_output_port->userdata = ( struct MMAL_PORT_USERDATA_*)
userdata;
if((ret = startCapture())!= 0)
{
delete userdata;
return false;
}
gettimeofday(&t0, 0);
sem_wait(&mutex);
sem_destroy(&mutex);
stopCapture();
delete userdata;
gettimeofday(&t1, 0);
elapsed = timedifference_msec(t0, t1);
printf("Code executed in %f milliseconds.\n", elapsed);
return true;
}
size_t Private_Impl_Still::getImageBufferSize() const
{
return width*height*3+54 ;//oversize the buffer so to fit BMP images
}
In the above function there is another function which is being called 'startcapture()' ...this is the function where the real capture takes place..to execute this function it takes around 5ms ..but after it returns it does a wait of about 3000ms using sem_wait(&mutex) ..when I remove this wait everything happens at 10ms but I get a completely black jpeg image. Now by making some settings to parameters such as ISO , brightness I am able to bring down the wait to 400ms using a usleep sunction
sem_wait(&mutex);It is there for purpose. Semaphore in OS is to ensure memory lock where memory is shared by another threads / processed. It is used to ensure that memory doesn't get overwritten by other processes. – dhruvvyas90 Jul 14 '15 at 12:09