#include "precomp.hpp"
#ifdef WIN32
#include "xiApi.h"
#else
#include <m3api/xiApi.h>
#endif
/**********************************************************************************/
class CvCaptureCAM_XIMEA : public CvCapture
{
public:
CvCaptureCAM_XIMEA() { init(); }
virtual ~CvCaptureCAM_XIMEA() { close(); }
virtual bool open( int index );
virtual void close();
virtual double getProperty(int) const;
virtual bool setProperty(int, double);
virtual bool grabFrame();
virtual IplImage* retrieveFrame(int);
virtual int getCaptureDomain() { return CV_CAP_XIAPI; } // Return the type of the capture object: CV_CAP_VFW, etc...
private:
void init();
void errMsg(const char* msg, int errNum);
void resetCvImage();
int getBpp();
IplImage* frame;
HANDLE hmv;
DWORD numDevices;
int timeout;
XI_IMG image;
};
/**********************************************************************************/
CvCapture* cvCreateCameraCapture_XIMEA( int index )
{
CvCaptureCAM_XIMEA* capture = new CvCaptureCAM_XIMEA;
if( capture->open( index ))
return capture;
delete capture;
return 0;
}
/**********************************************************************************/
// Enumerate connected devices
void CvCaptureCAM_XIMEA::init()
{
#if defined WIN32 || defined _WIN32
xiGetNumberDevices( &numDevices);
#else
// try second re-enumeration if first one fails
if (xiGetNumberDevices( &numDevices) != XI_OK)
{
xiGetNumberDevices( &numDevices);
}
#endif
hmv = NULL;
frame = NULL;
timeout = 0;
memset(&image, 0, sizeof(XI_IMG));
}
/**********************************************************************************/
// Initialize camera input
bool CvCaptureCAM_XIMEA::open( int wIndex )
{
#define HandleXiResult(res) if (res!=XI_OK) goto error;
int mvret = XI_OK;
if(numDevices == 0)
return false;
if((mvret = xiOpenDevice( wIndex, &hmv)) != XI_OK)
{
#if defined WIN32 || defined _WIN32
errMsg("Open XI_DEVICE failed", mvret);
return false;
#else
// try opening second time if first fails
if((mvret = xiOpenDevice( wIndex, &hmv)) != XI_OK)
{
errMsg("Open XI_DEVICE failed", mvret);
return false;
}
#endif
}
int width = 0;
int height = 0;
int isColor = 0;
// always use auto exposure/gain
mvret = xiSetParamInt( hmv, XI_PRM_AEAG, 1);
HandleXiResult(mvret);
mvret = xiGetParamInt( hmv, XI_PRM_WIDTH, &width);
HandleXiResult(mvret);
mvret = xiGetParamInt( hmv, XI_PRM_HEIGHT, &height);
HandleXiResult(mvret);
mvret = xiGetParamInt(hmv, XI_PRM_IMAGE_IS_COLOR, &isColor);
HandleXiResult(mvret);
if(isColor) // for color cameras
{
// default image format RGB24
mvret = xiSetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, XI_RGB24);
HandleXiResult(mvret);
// always use auto white balance for color cameras
mvret = xiSetParamInt( hmv, XI_PRM_AUTO_WB, 1);
HandleXiResult(mvret);
// allocate frame buffer for RGB24 image
frame = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
}
else // for mono cameras
{
// default image format MONO8
mvret = xiSetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, XI_MONO8);
HandleXiResult(mvret);
// allocate frame buffer for MONO8 image
frame = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
}
//default capture timeout 10s
timeout = 10000;
mvret = xiStartAcquisition(hmv);
if(mvret != XI_OK)
{
errMsg("StartAcquisition XI_DEVICE failed", mvret);
goto error;
}
return true;
error:
errMsg("Open XI_DEVICE failed", mvret);
xiCloseDevice(hmv);
hmv = NULL;
return false;
}
/**********************************************************************************/
void CvCaptureCAM_XIMEA::close()
{
if(frame)
cvReleaseImage(&frame);
if(hmv)
{
xiStopAcquisition(hmv);
xiCloseDevice(hmv);
}
hmv = NULL;
}
/**********************************************************************************/
bool CvCaptureCAM_XIMEA::grabFrame()
{
memset(&image, 0, sizeof(XI_IMG));
image.size = sizeof(XI_IMG);
int mvret = xiGetImage( hmv, timeout, &image);
if(mvret == XI_ACQUISITION_STOPED)
{
xiStartAcquisition(hmv);
mvret = xiGetImage(hmv, timeout, &image);
}
if(mvret != XI_OK)
{
errMsg("Error during GetImage", mvret);
return false;
}
return true;
}
/**********************************************************************************/
IplImage* CvCaptureCAM_XIMEA::retrieveFrame(int)
{
// update cvImage after format has changed
resetCvImage();
// copy pixel data
switch( image.frm)
{
case XI_MONO8 :
case XI_RAW8 : memcpy( frame->imageData, image.bp, image.width*image.height); break;
case XI_MONO16 :
case XI_RAW16 : memcpy( frame->imageData, image.bp, image.width*image.height*sizeof(WORD)); break;
case XI_RGB24 :
case XI_RGB_PLANAR : memcpy( frame->imageData, image.bp, image.width*image.height*3); break;
case XI_RGB32 : memcpy( frame->imageData, image.bp, image.width*image.height*4); break;
default: break;
}
return frame;
}
/**********************************************************************************/
void CvCaptureCAM_XIMEA::resetCvImage()
{
int width = 0, height = 0, format = 0;
xiGetParamInt( hmv, XI_PRM_WIDTH, &width);
xiGetParamInt( hmv, XI_PRM_HEIGHT, &height);
xiGetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, &format);
if( (int)image.width != frame->width || (int)image.height != frame->height || image.frm != (XI_IMG_FORMAT)format)
{
if(frame) cvReleaseImage(&frame);
frame = NULL;
switch( image.frm)
{
case XI_MONO8 :
case XI_RAW8 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_8U, 1); break;
case XI_MONO16 :
case XI_RAW16 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_16U, 1); break;
case XI_RGB24 :
case XI_RGB_PLANAR : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_8U, 3); break;
case XI_RGB32 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_8U, 4); break;
default :
return;
}
}
cvZero(frame);
}
/**********************************************************************************/
double CvCaptureCAM_XIMEA::getProperty( int property_id ) const
{
if(hmv == NULL)
return 0;
int ival = 0;
float fval = 0;
switch( property_id )
{
// OCV parameters
case CV_CAP_PROP_POS_FRAMES : return (double) image.nframe;
case CV_CAP_PROP_FRAME_WIDTH : xiGetParamInt( hmv, XI_PRM_WIDTH, &ival); return ival;
case CV_CAP_PROP_FRAME_HEIGHT : xiGetParamInt( hmv, XI_PRM_HEIGHT, &ival); return ival;
case CV_CAP_PROP_FPS : xiGetParamFloat( hmv, XI_PRM_FRAMERATE, &fval); return fval;
case CV_CAP_PROP_GAIN : xiGetParamFloat( hmv, XI_PRM_GAIN, &fval); return fval;
case CV_CAP_PROP_EXPOSURE : xiGetParamInt( hmv, XI_PRM_EXPOSURE, &ival); return ival;
// XIMEA camera properties
case CV_CAP_PROP_XI_DOWNSAMPLING : xiGetParamInt( hmv, XI_PRM_DOWNSAMPLING, &ival); return ival;
case CV_CAP_PROP_XI_DATA_FORMAT : xiGetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, &ival); return ival;
case CV_CAP_PROP_XI_OFFSET_X : xiGetParamInt( hmv, XI_PRM_OFFSET_X, &ival); return ival;
case CV_CAP_PROP_XI_OFFSET_Y : xiGetParamInt( hmv, XI_PRM_OFFSET_Y, &ival); return ival;
case CV_CAP_PROP_XI_TRG_SOURCE : xiGetParamInt( hmv, XI_PRM_TRG_SOURCE, &ival); return ival;
case CV_CAP_PROP_XI_GPI_SELECTOR : xiGetParamInt( hmv, XI_PRM_GPI_SELECTOR, &ival); return ival;
case CV_CAP_PROP_XI_GPI_MODE : xiGetParamInt( hmv, XI_PRM_GPI_MODE, &ival); return ival;
case CV_CAP_PROP_XI_GPI_LEVEL : xiGetParamInt( hmv, XI_PRM_GPI_LEVEL, &ival); return ival;
case CV_CAP_PROP_XI_GPO_SELECTOR : xiGetParamInt( hmv, XI_PRM_GPO_SELECTOR, &ival); return ival;
case CV_CAP_PROP_XI_GPO_MODE : xiGetParamInt( hmv, XI_PRM_GPO_MODE, &ival); return ival;
case CV_CAP_PROP_XI_LED_SELECTOR : xiGetParamInt( hmv, XI_PRM_LED_SELECTOR, &ival); return ival;
case CV_CAP_PROP_XI_LED_MODE : xiGetParamInt( hmv, XI_PRM_LED_MODE, &ival); return ival;
case CV_CAP_PROP_XI_AUTO_WB : xiGetParamInt( hmv, XI_PRM_AUTO_WB, &ival); return ival;
case CV_CAP_PROP_XI_AEAG : xiGetParamInt( hmv, XI_PRM_AEAG, &ival); return ival;
case CV_CAP_PROP_XI_EXP_PRIORITY : xiGetParamFloat( hmv, XI_PRM_EXP_PRIORITY, &fval); return fval;
case CV_CAP_PROP_XI_AE_MAX_LIMIT : xiGetParamInt( hmv, XI_PRM_AE_MAX_LIMIT, &ival); return ival;
case CV_CAP_PROP_XI_AG_MAX_LIMIT : xiGetParamFloat( hmv, XI_PRM_AG_MAX_LIMIT, &fval); return fval;
case CV_CAP_PROP_XI_AEAG_LEVEL : xiGetParamInt( hmv, XI_PRM_AEAG_LEVEL, &ival); return ival;
case CV_CAP_PROP_XI_TIMEOUT : return timeout;
}
return 0;
}
/**********************************************************************************/
bool CvCaptureCAM_XIMEA::setProperty( int property_id, double value )
{
int ival = (int) value;
float fval = (float) value;
int mvret = XI_OK;
switch(property_id)
{
// OCV parameters
case CV_CAP_PROP_FRAME_WIDTH : mvret = xiSetParamInt( hmv, XI_PRM_WIDTH, ival); break;
case CV_CAP_PROP_FRAME_HEIGHT : mvret = xiSetParamInt( hmv, XI_PRM_HEIGHT, ival); break;
case CV_CAP_PROP_FPS : mvret = xiSetParamFloat( hmv, XI_PRM_FRAMERATE, fval); break;
case CV_CAP_PROP_GAIN : mvret = xiSetParamFloat( hmv, XI_PRM_GAIN, fval); break;
case CV_CAP_PROP_EXPOSURE : mvret = xiSetParamInt( hmv, XI_PRM_EXPOSURE, ival); break;
// XIMEA camera properties
case CV_CAP_PROP_XI_DOWNSAMPLING : mvret = xiSetParamInt( hmv, XI_PRM_DOWNSAMPLING, ival); break;
case CV_CAP_PROP_XI_DATA_FORMAT : mvret = xiSetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, ival); break;
case CV_CAP_PROP_XI_OFFSET_X : mvret = xiSetParamInt( hmv, XI_PRM_OFFSET_X, ival); break;
case CV_CAP_PROP_XI_OFFSET_Y : mvret = xiSetParamInt( hmv, XI_PRM_OFFSET_Y, ival); break;
case CV_CAP_PROP_XI_TRG_SOURCE : mvret = xiSetParamInt( hmv, XI_PRM_TRG_SOURCE, ival); break;
case CV_CAP_PROP_XI_GPI_SELECTOR : mvret = xiSetParamInt( hmv, XI_PRM_GPI_SELECTOR, ival); break;
case CV_CAP_PROP_XI_TRG_SOFTWARE : mvret = xiSetParamInt( hmv, XI_PRM_TRG_SOFTWARE, 1); break;
case CV_CAP_PROP_XI_GPI_MODE : mvret = xiSetParamInt( hmv, XI_PRM_GPI_MODE, ival); break;
case CV_CAP_PROP_XI_GPI_LEVEL : mvret = xiSetParamInt( hmv, XI_PRM_GPI_LEVEL, ival); break;
case CV_CAP_PROP_XI_GPO_SELECTOR : mvret = xiSetParamInt( hmv, XI_PRM_GPO_SELECTOR, ival); break;
case CV_CAP_PROP_XI_GPO_MODE : mvret = xiSetParamInt( hmv, XI_PRM_GPO_MODE, ival); break;
case CV_CAP_PROP_XI_LED_SELECTOR : mvret = xiSetParamInt( hmv, XI_PRM_LED_SELECTOR, ival); break;
case CV_CAP_PROP_XI_LED_MODE : mvret = xiSetParamInt( hmv, XI_PRM_LED_MODE, ival); break;
case CV_CAP_PROP_XI_AUTO_WB : mvret = xiSetParamInt( hmv, XI_PRM_AUTO_WB, ival); break;
case CV_CAP_PROP_XI_MANUAL_WB : mvret = xiSetParamInt( hmv, XI_PRM_MANUAL_WB, ival); break;
case CV_CAP_PROP_XI_AEAG : mvret = xiSetParamInt( hmv, XI_PRM_AEAG, ival); break;
case CV_CAP_PROP_XI_EXP_PRIORITY : mvret = xiSetParamFloat( hmv, XI_PRM_EXP_PRIORITY, fval); break;
case CV_CAP_PROP_XI_AE_MAX_LIMIT : mvret = xiSetParamInt( hmv, XI_PRM_AE_MAX_LIMIT, ival); break;
case CV_CAP_PROP_XI_AG_MAX_LIMIT : mvret = xiSetParamFloat( hmv, XI_PRM_AG_MAX_LIMIT, fval); break;
case CV_CAP_PROP_XI_AEAG_LEVEL : mvret = xiSetParamInt( hmv, XI_PRM_AEAG_LEVEL, ival); break;
case CV_CAP_PROP_XI_TIMEOUT : timeout = ival; break;
}
if(mvret != XI_OK)
{
errMsg("Set parameter error", mvret);
return false;
}
else
return true;
}
/**********************************************************************************/
void CvCaptureCAM_XIMEA::errMsg(const char* msg, int errNum)
{
#if defined WIN32 || defined _WIN32
char buf[512]="";
sprintf( buf, "%s : %d\n", msg, errNum);
OutputDebugString(buf);
#else
fprintf(stderr, "%s : %d\n", msg, errNum);
#endif
}
/**********************************************************************************/
int CvCaptureCAM_XIMEA::getBpp()
{
switch( image.frm)
{
case XI_MONO8 :
case XI_RAW8 : return 1;
case XI_MONO16 :
case XI_RAW16 : return 2;
case XI_RGB24 :
case XI_RGB_PLANAR : return 3;
case XI_RGB32 : return 4;
default :
return 0;
}
}
/**********************************************************************************/