@ -51,7 +51,8 @@
//
// This file provides wrapper for using Aravis SDK library to access GigE Vision cameras.
// aravis-0.6 library shall be installed else this code will not be included in build.
// Aravis library (version 0.4 or 0.6) shall be installed else this code will not be included in build.
//
// To include this module invoke cmake with -DWITH_ARAVIS=ON
//
// Please obvserve, that jumbo frames are required when high fps & 16bit data is selected.
@ -60,11 +61,17 @@
// Basic usage: VideoCapture cap(CAP_ARAVIS + <camera id>);
//
// Supported properties:
// read/write
// CAP_PROP_AUTO_EXPOSURE(0|1)
// CAP_PROP_EXPOSURE(t), t in seconds
// CAP_PROP_GAIN(g), g >=0 or -1 for automatic control if CAP_PROP_AUTO_EXPOSURE is true
// CAP_PROP_FPS(f)
// CAP_PROP_FOURCC(type)
// CAP_PROP_BUFFERSIZE(n)
// read only:
// CAP_PROP_POS_MSEC
// CAP_PROP_FRAME_WIDTH
// CAP_PROP_FRAME_HEIGHT
//
// Supported types of data:
// video/x-raw, fourcc:'GREY' -> 8bit, 1 channel
@ -76,7 +83,7 @@
# define MODE_Y800 CV_FOURCC_MACRO('Y','8','0','0')
# define MODE_Y12 CV_FOURCC_MACRO('Y','1','2',' ')
# define BETWEEN(a,b,c) ((a) < (b) ? (b) : ((a) > (c) ? (c) : (a) ))
# define CLIP(a,b,c) (cv::max(cv::min((a),(c)),(b) ))
/********************* Capturing video from camera via Aravis *********************/
@ -141,15 +148,22 @@ protected:
int num_buffers ; // number of payload transmission buffers
ArvPixelFormat pixelFormat ; // current pixel format
int width ; // current width of frame
int height ; // current height of image
double fps ; // current fps
ArvPixelFormat pixelFormat ; // pixel format
int xoffset ; // current frame region x offset
int yoffset ; // current frame region y offset
int width ; // current frame width of frame
int height ; // current frame height of image
double fps ; // current value of fps
double exposure ; // current value of exposure time
double gain ; // current value of gain
double midGrey ; // current value of mid grey (brightness)
unsigned frameID ; // current frame id
unsigned prevFrameID ;
IplImage * frame ; // local frame copy
uint64_t framesCnt ; // number of retrieved frames
} ;
@ -162,10 +176,11 @@ CvCaptureCAM_Aravis::CvCaptureCAM_Aravis()
payload = 0 ;
widthMin = widthMax = heightMin = heightMax = 0 ;
xoffset = yoffset = width = height = 0 ;
fpsMin = fpsMax = gainMin = gainMax = exposureMin = exposureMax = 0 ;
controlExposure = false ;
targetGrey = 0 ;
framesCnt = 0 ;
frameID = prevFrameID = 0 ;
num_buffers = 50 ;
frame = NULL ;
@ -175,13 +190,16 @@ void CvCaptureCAM_Aravis::close()
{
if ( camera )
stopCapture ( ) ;
g_object_unref ( camera ) ;
camera = NULL ;
}
bool CvCaptureCAM_Aravis : : getDeviceNameById ( int id , std : : string & device )
{
arv_update_device_list ( ) ;
if ( id > 0 & & id < arv_get_n_devices ( ) ) {
if ( ( id > = 0 ) & & ( id < ( int ) arv_get_n_devices ( ) ) ) {
device = arv_get_device_id ( id ) ;
return true ;
}
@ -268,11 +286,15 @@ bool CvCaptureCAM_Aravis::grabFrame()
arv_stream_push_buffer ( stream , arv_buffer ) ;
} else break ;
}
if ( tries < max_tries ) {
if ( arv_buffer ! = NULL & & tries < max_tries ) {
size_t buffer_size ;
framebuffer = ( void * ) arv_buffer_get_data ( arv_buffer , & buffer_size ) ;
arv_buffer_get_image_region ( arv_buffer , NULL , NULL , & width , & height ) ;
// retieve image size properites
arv_buffer_get_image_region ( arv_buffer , & xoffset , & yoffset , & width , & height ) ;
// retieve image ID set by camera
frameID = arv_buffer_get_frame_id ( arv_buffer ) ;
arv_stream_push_buffer ( stream , arv_buffer ) ;
return true ;
@ -311,13 +333,12 @@ IplImage* CvCaptureCAM_Aravis::retrieveFrame(int)
}
cvCopy ( & src , frame ) ;
if ( controlExposure & & ! ( framesCnt % 2 ) ) {
if ( controlExposure & & ( ( frameID - prevFrameID ) > 1 ) ) {
// control exposure every second frame
// i.e. skip frame taken with previous exposure setup
autoExposureControl ( frame ) ;
}
framesCnt + + ;
return frame ;
}
}
@ -344,18 +365,21 @@ void CvCaptureCAM_Aravis::autoExposureControl(IplImage* image)
// distance from optimal value as a percentage
double d = ( targetGrey * dmid ) / brightness ;
if ( d > = dmid ) d = ( d + ( dmid * 2 ) ) / 3 ;
prevFrameID = frameID ;
midGrey = brightness ;
double maxe = 1e6 / fps ;
double ne = CLIP ( ( exposure * d ) / dmid , exposureMin , maxe ) ;
// if change of value requires intervention
if ( fabs ( d - dmid ) > 5 ) {
if ( d > = dmid ) d = ( d + ( dmid * 2 ) ) / 3 ;
double ng = 0 , ne = 0 , maxe = 1e6 / fps ;
double ev = log ( d / dmid ) / log ( 2 ) ;
double ev , ng = 0 ;
if ( gainAvailable & & autoGain ) {
// depending on device single gain step may equal to 1 or 1/3 EV
double ngg = gain + ev ;
ng = BETWEEN ( ngg , gainMin , gainMax ) ;
ev = log ( d / dmid ) / log ( 2 ) ;
ng = CLIP ( gain + ev , gainMin , gainMax ) ;
if ( ng < gain ) {
// piority 1 - reduce gain
@ -365,13 +389,9 @@ void CvCaptureCAM_Aravis::autoExposureControl(IplImage* image)
}
if ( exposureAvailable ) {
double nee = ( exposure * d ) / dmid ;
ne = BETWEEN ( nee , exposureMin , maxe ) ;
if ( abs ( exposure - ne ) > 2 ) {
// priority 2 - control of exposure time
arv_camera_set_exposure_time ( camera , ( exposure = ne ) ) ;
return ;
}
}
@ -379,28 +399,39 @@ void CvCaptureCAM_Aravis::autoExposureControl(IplImage* image)
if ( gainAvailable & & autoGain ) {
if ( exposureAvailable ) {
// exposure at maximum - increase gain if possible
if ( ng > gain & & ne > = maxe ) {
if ( ng < gainMax ) {
if ( ng > gain & & ng < gainMax & & ne > = maxe ) {
arv_camera_set_gain ( camera , ( gain = ng ) ) ;
return ;
}
} else {
// priority 3 - increase gain
arv_camera_set_gain ( camera , ( gain = ng ) ) ;
return ;
}
}
}
// if gain can be reduced - do it
if ( gainAvailable & & autoGain & & exposureAvailable ) {
if ( gain > gainMin & & exposure < maxe ) {
exposure = BETWEEN ( ne * 1.05 , exposureMin , maxe ) ;
exposure = CLIP ( ne * 1.05 , exposureMin , maxe ) ;
arv_camera_set_exposure_time ( camera , exposure ) ;
}
} else {
arv_camera_set_gain ( camera , ( gain = ng ) ) ;
}
}
}
}
double CvCaptureCAM_Aravis : : getProperty ( int property_id ) const
{
switch ( property_id ) {
case CV_CAP_PROP_POS_MSEC :
return ( double ) frameID / fps ;
case CV_CAP_PROP_FRAME_WIDTH :
return width ;
case CV_CAP_PROP_FRAME_HEIGHT :
return height ;
case CV_CAP_PROP_AUTO_EXPOSURE :
return ( controlExposure ? 1 : 0 ) ;
@ -433,6 +464,16 @@ double CvCaptureCAM_Aravis::getProperty( int property_id ) const
return MODE_Y12 ;
}
}
break ;
case CV_CAP_PROP_BUFFERSIZE :
if ( stream ) {
int in , out ;
arv_stream_get_n_buffers ( stream , & in , & out ) ;
// return number of available buffers in Aravis output queue
return out ;
}
break ;
}
return - 1.0 ;
}
@ -454,13 +495,13 @@ bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
/* exposure time in seconds, like 1/100 s */
value * = 1e6 ; // -> from s to us
arv_camera_set_exposure_time ( camera , exposure = BETWEEN ( value , exposureMin , exposureMax ) ) ;
arv_camera_set_exposure_time ( camera , exposure = CLIP ( value , exposureMin , exposureMax ) ) ;
break ;
} else return false ;
case CV_CAP_PROP_FPS :
if ( fpsAvailable ) {
arv_camera_set_frame_rate ( camera , fps = BETWEEN ( value , fpsMin , fpsMax ) ) ;
arv_camera_set_frame_rate ( camera , fps = CLIP ( value , fpsMin , fpsMax ) ) ;
break ;
} else return false ;
@ -469,7 +510,7 @@ bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
if ( ( autoGain = ( - 1 = = value ) ) )
break ;
arv_camera_set_gain ( camera , gain = BETWEEN ( value , gainMin , gainMax ) ) ;
arv_camera_set_gain ( camera , gain = CLIP ( value , gainMin , gainMax ) ) ;
break ;
} else return false ;
@ -495,6 +536,18 @@ bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
}
break ;
case CV_CAP_PROP_BUFFERSIZE :
{
int x = ( int ) value ;
if ( ( x > 0 ) & & ( x ! = num_buffers ) ) {
stopCapture ( ) ;
num_buffers = x ;
startCapture ( ) ;
}
}
break ;
default :
return false ;
}