//
// 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.
// 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
#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 *********************/
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
};
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;
{
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;
}
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;
}
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;
}
}
// 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
}
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;
}
}
if(gainAvailable && autoGain) {
if(exposureAvailable) {
// exposure at maximum - increase gain if possible
- if(ng > gain && ne >= maxe) {
- if(ng < gainMax) {
- arv_camera_set_gain(camera, (gain = ng));
- }
+ if(ng > gain && ng < gainMax && ne >= maxe) {
+ arv_camera_set_gain(camera, (gain = ng));
return;
}
-
- // if gain can be reduced - do it
- if(gain > gainMin && exposure < maxe) {
- exposure = BETWEEN( ne * 1.05, exposureMin, maxe);
- arv_camera_set_exposure_time(camera, exposure );
- }
} 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 = CLIP( ne * 1.05, exposureMin, maxe);
+ arv_camera_set_exposure_time(camera, exposure );
+ }
+ }
}
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);
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;
}
/* 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;
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;
}
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;
}