2

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

  • Perhaps shutter is too quick? Try flashing a flash light into the camera, maybe you will see something? – Piotr Kamoda Jul 14 '15 at 9:33
  • Please don't take off 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
  • sem_wait(&mutex) takes around 3000ms , is it the time taken for an actual capture or to lock the memory so that its not overwritten ..is there any possible way of how I can overcome this – user5049377 Jul 15 '15 at 5:21
  • and I tried changing the shutter speed & using a flash from my mobile ..that does help to an extent reducing the wait time from 3000ms to around 450 but can't eliminate it completely – user5049377 Jul 15 '15 at 5:26
1

This is a hardware question, not an RPi question.

The short answer is, "you can't do that."

A CCD camera works by charging up capacitors. If you don't give the capacitors any time to charge, then you will get a dark image. If you want a faster camera, then you have to pay more money.

| improve this answer | |
  • This might be the issue here, although the camera module is rated for 60fps @ 720p, which would get us down as far 16.7ms per frame. – goobering Feb 8 '16 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.