From 3923484341ec8366520879cea7296ffe8e87398c Mon Sep 17 00:00:00 2001 From: askforeric Date: Tue, 13 Nov 2012 16:10:22 -0500 Subject: [PATCH] Refactored the PvAPI capture class to better facilitate dynamic property changes - Added Gain control - Changed default acquisition mode to grayscale - Fixed a signed/unsigned compare issue - Implemented frame resizing - Implemented automatic buffer resizing on frame resize - Corrected camera initialization so that it attempts to put the camera in Mono8 but does not fail if this doesn't succeed. --- modules/highgui/src/cap_pvapi.cpp | 325 ++++++++++++++++++++++++++------------ 1 file changed, 228 insertions(+), 97 deletions(-) diff --git a/modules/highgui/src/cap_pvapi.cpp b/modules/highgui/src/cap_pvapi.cpp index fe94d8c..8d4a4a2 100644 --- a/modules/highgui/src/cap_pvapi.cpp +++ b/modules/highgui/src/cap_pvapi.cpp @@ -95,6 +95,10 @@ protected: virtual void Sleep(unsigned int time); #endif + void stopCapture(); + bool startCapture(); + bool resizeCaptureFrame (int frameWidth, int frameHeight); + typedef struct { unsigned long UID; @@ -113,6 +117,8 @@ protected: CvCaptureCAM_PvAPI::CvCaptureCAM_PvAPI() { monocrome=false; + frame = NULL; + grayframe = NULL; memset(&this->Camera, 0, sizeof(this->Camera)); } @@ -132,8 +138,7 @@ void CvCaptureCAM_PvAPI::Sleep(unsigned int time) void CvCaptureCAM_PvAPI::close() { // Stop the acquisition & free the camera - PvCommandRun(Camera.Handle, "AcquisitionStop"); - PvCaptureEnd(Camera.Handle); + stopCapture(); PvCameraClose(Camera.Handle); PvUnInitialize(); } @@ -162,7 +167,8 @@ bool CvCaptureCAM_PvAPI::open( int index ) Camera.UID = cameraList[index].UniqueId; - if (!PvCameraInfo(Camera.UID,&camInfo) && !PvCameraIpSettingsGet(Camera.UID,&ipSettings)) { + if (!PvCameraInfo(Camera.UID,&camInfo) && !PvCameraIpSettingsGet(Camera.UID,&ipSettings)) + { /* struct in_addr addr; addr.s_addr = ipSettings.CurrentIpAddress; @@ -173,7 +179,8 @@ bool CvCaptureCAM_PvAPI::open( int index ) printf("Current gateway:\t%s\n",inet_ntoa(addr)); */ } - else { + else + { fprintf(stderr,"ERROR: could not retrieve camera IP settings.\n"); return false; } @@ -181,73 +188,33 @@ bool CvCaptureCAM_PvAPI::open( int index ) if (PvCameraOpen(Camera.UID, ePvAccessMaster, &(Camera.Handle))==ePvErrSuccess) { - - //Set Pixel Format to BRG24 to follow conventions - /*Errcode = PvAttrEnumSet(Camera.Handle, "PixelFormat", "Bgr24"); - if (Errcode != ePvErrSuccess) - { - fprintf(stderr, "PvAPI: couldn't set PixelFormat to Bgr24\n"); - return NULL; - } - */ - tPvUint32 frameWidth, frameHeight, frameSize; + tPvUint32 frameWidth, frameHeight; unsigned long maxSize; - char pixelFormat[256]; - PvAttrUint32Get(Camera.Handle, "TotalBytesPerFrame", &frameSize); + + // By Default, try to set the pixel format to Mono8. This can be changed later + // via calls to setProperty. Some colour cameras (i.e. the Manta line) have a default + // image mode of Bayer8, which is currently unsupported, so Mono8 is a safe bet for + // startup. + + monocrome = (PvAttrEnumSet(Camera.Handle, "PixelFormat", "Mono8") == ePvErrSuccess); + PvAttrUint32Get(Camera.Handle, "Width", &frameWidth); PvAttrUint32Get(Camera.Handle, "Height", &frameHeight); - PvAttrEnumGet(Camera.Handle, "PixelFormat", pixelFormat,256,NULL); + + // Determine the maximum packet size supported by the system (ethernet adapter) + // and then configure the camera to use this value. If the system's NIC only supports + // an MTU of 1500 or lower, this will automatically configure an MTU of 1500. + // 8228 is the optimal size described by the API in order to enable jumbo frames + maxSize = 8228; //PvAttrUint32Get(Camera.Handle,"PacketSize",&maxSize); if (PvCaptureAdjustPacketSize(Camera.Handle,maxSize)!=ePvErrSuccess) return false; - if (strcmp(pixelFormat, "Mono8")==0) { - grayframe = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 1); - grayframe->widthStep = (int)frameWidth; - frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 3); - frame->widthStep = (int)frameWidth*3; - Camera.Frame.ImageBufferSize = frameSize; - Camera.Frame.ImageBuffer = grayframe->imageData; - } - else if (strcmp(pixelFormat, "Mono16")==0) { - grayframe = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_16U, 1); - grayframe->widthStep = (int)frameWidth; - frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_16U, 3); - frame->widthStep = (int)frameWidth*3; - Camera.Frame.ImageBufferSize = frameSize; - Camera.Frame.ImageBuffer = grayframe->imageData; - } - else if (strcmp(pixelFormat, "Bgr24")==0) { - frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 3); - frame->widthStep = (int)frameWidth*3; - Camera.Frame.ImageBufferSize = frameSize; - Camera.Frame.ImageBuffer = frame->imageData; - } - else - return false; - // Start the camera - PvCaptureStart(Camera.Handle); - - // Set the camera to capture continuously - if(PvAttrEnumSet(Camera.Handle, "AcquisitionMode", "Continuous")!= ePvErrSuccess) - { - fprintf(stderr,"Could not set Prosilica Acquisition Mode\n"); - return false; - } - if(PvCommandRun(Camera.Handle, "AcquisitionStart")!= ePvErrSuccess) - { - fprintf(stderr,"Could not start Prosilica acquisition\n"); - return false; - } + resizeCaptureFrame(frameWidth, frameHeight); - if(PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "Freerun")!= ePvErrSuccess) - { - fprintf(stderr,"Error setting Prosilica trigger to \"Freerun\""); - return false; - } + return startCapture(); - return true; } fprintf(stderr,"Error cannot open camera\n"); return false; @@ -264,8 +231,10 @@ bool CvCaptureCAM_PvAPI::grabFrame() IplImage* CvCaptureCAM_PvAPI::retrieveFrame(int) { - if (PvCaptureWaitForFrameDone(Camera.Handle, &(Camera.Frame), 1000) == ePvErrSuccess) { - if (!monocrome) { + if (PvCaptureWaitForFrameDone(Camera.Handle, &(Camera.Frame), 1000) == ePvErrSuccess) + { + if (!monocrome) + { cvMerge(grayframe,grayframe,grayframe,NULL,frame); return frame; } @@ -287,26 +256,31 @@ double CvCaptureCAM_PvAPI::getProperty( int property_id ) PvAttrUint32Get(Camera.Handle, "Height", &nTemp); return (double)nTemp; case CV_CAP_PROP_EXPOSURE: - PvAttrUint32Get(Camera.Handle,"ExposureValue",&nTemp); - return (double)nTemp; + PvAttrUint32Get(Camera.Handle,"ExposureValue",&nTemp); + return (double)nTemp; case CV_CAP_PROP_FPS: - tPvFloat32 nfTemp; + tPvFloat32 nfTemp; PvAttrFloat32Get(Camera.Handle, "StatFrameRate", &nfTemp); return (double)nfTemp; case CV_CAP_PROP_PVAPI_MULTICASTIP: - char mEnable[2]; - char mIp[11]; - PvAttrEnumGet(Camera.Handle,"MulticastEnable",mEnable,sizeof(mEnable),NULL); - if (strcmp(mEnable, "Off") == 0) { - return -1; - } - else { - long int ip; - int a,b,c,d; - PvAttrStringGet(Camera.Handle, "MulticastIPAddress",mIp,sizeof(mIp),NULL); - sscanf(mIp, "%d.%d.%d.%d", &a, &b, &c, &d); ip = ((a*256 + b)*256 + c)*256 + d; - return (double)ip; - } + char mEnable[2]; + char mIp[11]; + PvAttrEnumGet(Camera.Handle,"MulticastEnable",mEnable,sizeof(mEnable),NULL); + if (strcmp(mEnable, "Off") == 0) + { + return -1; + } + else + { + long int ip; + int a,b,c,d; + PvAttrStringGet(Camera.Handle, "MulticastIPAddress",mIp,sizeof(mIp),NULL); + sscanf(mIp, "%d.%d.%d.%d", &a, &b, &c, &d); ip = ((a*256 + b)*256 + c)*256 + d; + return (double)ip; + } + case CV_CAP_PROP_GAIN: + PvAttrUint32Get(Camera.Handle, "GainValue", &nTemp); + return (double)nTemp; } return -1.0; } @@ -315,19 +289,50 @@ bool CvCaptureCAM_PvAPI::setProperty( int property_id, double value ) { switch ( property_id ) { - /* TODO: Camera works, but IplImage must be modified for the new size case CV_CAP_PROP_FRAME_WIDTH: - PvAttrUint32Set(Camera.Handle, "Width", (tPvUint32)value); + { + tPvUint32 currHeight; + + PvAttrUint32Get(Camera.Handle, "Height", &currHeight); + + stopCapture(); + // Reallocate Frames + if (!resizeCaptureFrame(value, currHeight)) + { + startCapture(); + return false; + } + + startCapture(); + break; + } case CV_CAP_PROP_FRAME_HEIGHT: - PvAttrUint32Set(Camera.Handle, "Heigth", (tPvUint32)value); + { + tPvUint32 currWidth; + + PvAttrUint32Get(Camera.Handle, "Width", &currWidth); + + stopCapture(); + + // Reallocate Frames + if (!resizeCaptureFrame(value, currWidth)) + { + startCapture(); + return false; + } + + startCapture(); + break; - */ + } case CV_CAP_PROP_MONOCROME: - if (value==1) { + if (value==1) + { char pixelFormat[256]; PvAttrEnumGet(Camera.Handle, "PixelFormat", pixelFormat,256,NULL); - if ((strcmp(pixelFormat, "Mono8")==0) || strcmp(pixelFormat, "Mono16")==0) { + if ((strcmp(pixelFormat, "Mono8")==0) || strcmp(pixelFormat, "Mono16")==0) + { monocrome=true; } else @@ -338,31 +343,157 @@ bool CvCaptureCAM_PvAPI::setProperty( int property_id, double value ) break; case CV_CAP_PROP_EXPOSURE: if ((PvAttrUint32Set(Camera.Handle,"ExposureValue",(tPvUint32)value)==ePvErrSuccess)) - break; - else - return false; - case CV_CAP_PROP_PVAPI_MULTICASTIP: - - if (value==-1) { - if ((PvAttrEnumSet(Camera.Handle,"MulticastEnable", "Off")==ePvErrSuccess)) break; else return false; + case CV_CAP_PROP_PVAPI_MULTICASTIP: + if (value==-1) + { + if ((PvAttrEnumSet(Camera.Handle,"MulticastEnable", "Off")==ePvErrSuccess)) + break; + else + return false; } - else { - std::string ip=cv::format("%d.%d.%d.%d", ((int)value>>24)&255, ((int)value>>16)&255, ((int)value>>8)&255, (int)value&255); - if ((PvAttrEnumSet(Camera.Handle,"MulticastEnable", "On")==ePvErrSuccess) && - (PvAttrStringSet(Camera.Handle, "MulticastIPAddress", ip.c_str())==ePvErrSuccess)) - break; else + { + std::string ip=cv::format("%d.%d.%d.%d", ((int)value>>24)&255, ((int)value>>16)&255, ((int)value>>8)&255, (int)value&255); + if ((PvAttrEnumSet(Camera.Handle,"MulticastEnable", "On")==ePvErrSuccess) && + (PvAttrStringSet(Camera.Handle, "MulticastIPAddress", ip.c_str())==ePvErrSuccess)) + break; + else + return false; + } + case CV_CAP_PROP_GAIN: + if (PvAttrUint32Set(Camera.Handle,"GainValue",(tPvUint32)value)!=ePvErrSuccess) + { return false; } + break; default: return false; } return true; } +void CvCaptureCAM_PvAPI::stopCapture() +{ + PvCommandRun(Camera.Handle, "AcquisitionStop"); + PvCaptureEnd(Camera.Handle); +} + +bool CvCaptureCAM_PvAPI::startCapture() +{ + // Start the camera + PvCaptureStart(Camera.Handle); + + // Set the camera to capture continuously + if(PvAttrEnumSet(Camera.Handle, "AcquisitionMode", "Continuous")!= ePvErrSuccess) + { + fprintf(stderr,"Could not set PvAPI Acquisition Mode\n"); + return false; + } + + if(PvCommandRun(Camera.Handle, "AcquisitionStart")!= ePvErrSuccess) + { + fprintf(stderr,"Could not start PvAPI acquisition\n"); + return false; + } + + if(PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "Freerun")!= ePvErrSuccess) + { + fprintf(stderr,"Error setting PvAPI trigger to \"Freerun\""); + return false; + } + + return true; +} + +bool CvCaptureCAM_PvAPI::resizeCaptureFrame (int frameWidth, int frameHeight) +{ + char pixelFormat[256]; + tPvUint32 frameSize; + tPvUint32 sensorHeight; + tPvUint32 sensorWidth; + + + if (grayframe) + { + cvReleaseImage(&grayframe); + grayframe = NULL; + } + + if (frame) + { + cvReleaseImage(&frame); + frame = NULL; + } + + if (PvAttrUint32Get(Camera.Handle, "SensorWidth", &sensorWidth) != ePvErrSuccess) + { + return false; + } + + if (PvAttrUint32Get(Camera.Handle, "SensorHeight", &sensorHeight) != ePvErrSuccess) + { + return false; + } + + // Cap out of bounds widths to the max supported by the sensor + if ((frameWidth < 0) || ((tPvUint32)frameWidth > sensorWidth)) + { + frameWidth = sensorWidth; + } + + if ((frameHeight < 0) || ((tPvUint32)frameHeight > sensorHeight)) + { + frameHeight = sensorHeight; + } + + + if (PvAttrUint32Set(Camera.Handle, "Height", frameHeight) != ePvErrSuccess) + { + return false; + } + + if (PvAttrUint32Set(Camera.Handle, "Width", frameWidth) != ePvErrSuccess) + { + return false; + } + + PvAttrEnumGet(Camera.Handle, "PixelFormat", pixelFormat,256,NULL); + PvAttrUint32Get(Camera.Handle, "TotalBytesPerFrame", &frameSize); + + + if (strcmp(pixelFormat, "Mono8")==0) + { + grayframe = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 1); + grayframe->widthStep = (int)frameWidth; + frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 3); + frame->widthStep = (int)frameWidth*3; + Camera.Frame.ImageBufferSize = frameSize; + Camera.Frame.ImageBuffer = grayframe->imageData; + } + else if (strcmp(pixelFormat, "Mono16")==0) + { + grayframe = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_16U, 1); + grayframe->widthStep = (int)frameWidth; + frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_16U, 3); + frame->widthStep = (int)frameWidth*3; + Camera.Frame.ImageBufferSize = frameSize; + Camera.Frame.ImageBuffer = grayframe->imageData; + } + else if (strcmp(pixelFormat, "Bgr24")==0) + { + frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 3); + frame->widthStep = (int)frameWidth*3; + Camera.Frame.ImageBufferSize = frameSize; + Camera.Frame.ImageBuffer = frame->imageData; + } + else + return false; + + return true; +} CvCapture* cvCreateCameraCapture_PvAPI( int index ) { -- 2.7.4