FLI libflipro API
SimpleHWMerging.cpp

Simple Hardware Merging Example Code.
This example shows you how to create a simple image loop and use the Hardware merging capabilities on the PCIE Fiber interface card to unpack and merge the image planes. NOTE: THIS EXAMPLE REQURIES THE INSTALLATION AND CONNECTION OF THE PCIE Fiber Interface card.

#include "stdint.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include <string>
#include "libflipro.h"
#define FLI_TEST_MAX_SUPPORTED_CAMERAS (4)
// Static Function declarations
static int32_t SetFrameInfo(int32_t iDeviceHandle, uint32_t uiWidth, uint32_t uiHeight);
static std::string MakeProcessedFileName(std::string& rstrFileName, uint32_t uiFrameNumber, const char* pSuffix, const char* pExt);
static void SaveProcessedFile(std::string strFileName, uint8_t* pMetaData, uint32_t uiMetaSize, uint8_t* pImageData, uint64_t uiImageByteSize);
static int32_t CheckReferenceMetaData(FILE* pFile);
static int32_t SendHWMergeReferenceFiles(int32_t iHandle, char* pDSNUFileName, char* pPRNUFileName, uint32_t uiWidth, uint32_t uiHeight);
// Static Data declarations
static int32_t s_iDeviceHandle;
uint32_t uiNumDetectedDevices;
static FPRODEVICEINFO s_camDeviceInfo[FLI_TEST_MAX_SUPPORTED_CAMERAS];
static uint32_t s_uiCaps[(uint32_t)FPROCAPS::FPROCAP_NUM];
//static const char* DSNU_FILE_NAME = "REF_DSNU_Data_4040.rcd";
//static const char* PRNU_FILE_NAME = "REF_PRNU_Data_4040.rcd";
int main()
{
int32_t iResult;
int32_t iGrabResult;
uint32_t i;
uint8_t *pFrame;
uint32_t uiFramSizeInBytes;
FPRO_HWMERGEENABLE mergeEnables;
FPRO_REFFRAMES refFrames;
std::string strFileName;
uint32_t uiCapNum;
pFrame = NULL;
// first get the list of available devices
uiNumDetectedDevices = FLI_TEST_MAX_SUPPORTED_CAMERAS;
iResult = FPROCam_GetCameraList(s_camDeviceInfo, &uiNumDetectedDevices);
if ((iResult >= 0) && (uiNumDetectedDevices > 0))
{
if (FPROCONNECTION::FPRO_CONNECTION_FIBRE == s_camDeviceInfo[0].conInfo.eConnType)
{
// Open the first device in the list
s_iDeviceHandle = -1;
iResult = FPROCam_Open(&s_camDeviceInfo[0], &s_iDeviceHandle);
if ((iResult >= 0) && (s_iDeviceHandle >= 0))
{
// This is not strictly required but we use the information in the
// capabilities structure to set the appropriate image dimensions
// for the camera model.
uiCapNum = (uint32_t)FPROCAPS::FPROCAP_NUM;
iResult= FPROSensor_GetCapabilityList(s_iDeviceHandle, s_uiCaps, &uiCapNum);
// Set up merging identity frames- full frame size.
// Note: if you chnage the gain setting, you must call this function afterwards in
// order to reset the identity frames. See FPROAlgo_SetHardwareMergeReferenceFrames
// in the documentation for more information.
memset(&refFrames, 0, sizeof(refFrames));
refFrames.uiWidth = s_uiCaps[(uint32_t)FPROCAPS::FPROCAP_MAX_PIXEL_WIDTH];
refFrames.uiHeight = s_uiCaps[(uint32_t)FPROCAPS::FPROCAP_MAX_PIXEL_HEIGHT];
FPROAlgo_SetHardwareMergeReferenceFrames(s_iDeviceHandle, &refFrames);
// In general, you will need to send the appropriate reference frames
// to the API in order to get the best merge results. The above call gets things set up
// for the simplest case. If you have created reference files, you can send them using
// the example function below. If no files are given to the API or in the case of using
// identity frames as set up in the above call,
// the merge algorithm computes a set of reference frames based on the sensor gain values in
// the image Meta Data. This is a global calculation and not as refined as the per pixel
// reference files that should be created and used. This example function here expects
// reference files created by the FLI Pilot application. If you
// generate your own files, you will need to develop your own implementation.
// If you have created reference files with Pilot, you can use the FPROAlgo_SetHardwareMergeReferenceFiles()
// function to setup the API. If not, you will have to refer to the example function below.
// See the documentation for FPROAlgo_SetHardwareMergeReferenceFrames()
// for a description of this function and parameters.
//SendHWMergeReferenceFiles(s_iDeviceHandle, (char*)DSNU_FILE_NAME, (char*)PRNU_FILE_NAME, 4096, 4096);
// You can also adjust the merging algorithm with the following function.
// This function is optional as default thresholds are already set up in the API.
// See the documentation for a description of this function and parameters.
// FPROAlgo_SetHardwareMergeThresholds(int32_t iHandle, uint16_t uiHighGainThreshold, uint16_t uiMergeDifferenceThreshold);
// You also need to set up the merge enables when using the API for merging images (or for
// hardware merging using the PCIE Fibre card). NOTE: The bMergeEnable flag below is
// set to true! This enables the merging to be done by the PCIE Fiber Interface card.
// See the SimpleAPIMerging sample if you do not have one of these cards.
mergeEnables.bMergeEnable = true;
if (iResult >= 0)
iResult= FPROAlgo_SetHardwareMergeEnables(s_iDeviceHandle, mergeEnables);
// Set up your exposure and frame parameters
if (iResult >= 0)
iResult = SetFrameInfo(s_iDeviceHandle, s_uiCaps[(uint32_t)FPROCAPS::FPROCAP_MAX_PIXEL_WIDTH], s_uiCaps[(uint32_t)FPROCAPS::FPROCAP_MAX_PIXEL_HEIGHT]);
if (iResult >= 0)
{
// Make sure we have space for the raw image frame. See the SimpleImageLoop.cpp sample
// for an explanation of this call.
uiFramSizeInBytes = FPROFrame_ComputeFrameSize(s_iDeviceHandle);
pFrame = (uint8_t *)malloc(uiFramSizeInBytes);
if (pFrame)
{
if (iResult >= 0)
{
// all is well - now you can start grabbing image frames
// This loop will grab 10 frames. Note there is no more set up
// of the fproUnpacked structure within this loop. The API allocated
// the requested buffers the first time through and are reused on subsequent
// passes. If you change imaging parameters, you must free the buffers and
// re-initialize with the new settings. The buffers are free'd below after
// the loop terminates.
iGrabResult = 0;
for (i = 0; (i < 10) && (iResult >= 0) && (iGrabResult >= 0); ++i)
{
// Start the capture and tell it to get 1 frame
iResult = FPROFrame_CaptureStart(s_iDeviceHandle, 1);
if (iResult >= 0)
{
// Grab the frame- typically the timeout passed is the exposure time. We pass 0 because our
// exposure time is small (50 msecs). See SetFrameInfo() below.
iGrabResult = FPROFrame_GetVideoFrame(s_iDeviceHandle, pFrame, &uiFramSizeInBytes, 0);
// Regardless of how the capture turned out, stop the capture
iResult = FPROFrame_CaptureAbort(s_iDeviceHandle);
// If the FPROFrame_GetVideoFrame() succeeded- then process it
if (iGrabResult >= 0)
{
printf("Got frame %d.\n",i);
#if 1
strFileName = "HW_Unpack_Sample.rcd";
SaveProcessedFile(MakeProcessedFileName(strFileName, i, "_MERGED16", ".rcd"), NULL, 0, (uint8_t*)pFrame, uiFramSizeInBytes);
#endif
}
}
}
}
}
else
{
printf("ERROR getting frame memory.... leaving\n");
}
}
// Close up shop
iResult = FPROCam_Close(s_iDeviceHandle);
}
}
else
{
printf("ERROR: Connection must be PCIE Fiber connection for this sample code to run correctly!\n");
}
}
else
{
printf("ERROR: No cameras detected!\n\n");
}
// Give our memory back
if (pFrame)
free(pFrame);
return 0;
}
int32_t
SetFrameInfo(int32_t iDeviceHandle, uint32_t uiWidth, uint32_t uiHeight)
{
int32_t iResult;
// assume success
iResult = 0;
// Enable/disable image data
// The power on default of the camera is to have image data enabled.
// This is just shown here in case you are working with test frames and
// need to set the camera back up to get you real image data.
iResult = FPROFrame_SetImageDataEnable(iDeviceHandle, true);
// Set the exposure time
// The default camera exposure time is 50msecs (for the GSENSE 400)
// The FPROCtrl_SetExposureTime() API expects the exposure time in
// nano seconds. The frameDelay parameter is also in nanoseconds
if (iResult >= 0)
iResult = FPROCtrl_SetExposure(iDeviceHandle, 50000000,10000000,false);
// Set the Image area
if (iResult >= 0)
iResult = FPROFrame_SetImageArea(iDeviceHandle, 0, 0, uiWidth, uiHeight);
// return our result
return(iResult);
}
std::string MakeProcessedFileName(std::string & rstrFileName, uint32_t uiFrameNumber, const char* pSuffix, const char* pExt)
{
std::string strNew;
std::string strExt;
char cNumBuff[32];
size_t iIndex;
// find the last '.' in the file name-
iIndex = rstrFileName.find_last_of('.', rstrFileName.length());
if (iIndex != std::string::npos)
{
strNew = rstrFileName.substr(0,iIndex);
snprintf(cNumBuff, sizeof(cNumBuff), "_%d_", uiFrameNumber);
strNew += cNumBuff;
strNew += pSuffix;
}
else
{
// No '.', just add the suffix to the end
strNew = rstrFileName + pSuffix;
}
strNew += pExt;
return(strNew);
}
void SaveProcessedFile(std::string rstrFileName, uint8_t* pMetaData, uint32_t uiMetaSize, uint8_t* pImageData, uint64_t uiImageByteSize)
{
FILE* pFile;
int32_t iResult;
#if defined(_WIN32) || defined(_WINDOWS)
fopen_s(&pFile, rstrFileName.c_str(), "w+b");
#else
pFile= fopen(rstrFileName.c_str(), "w+b");
#endif
if (pFile)
{
iResult = 0;
if (pMetaData)
{
if (fwrite(pMetaData, 1, uiMetaSize, pFile) != uiMetaSize)
{
printf("Error writing Meta Data to file %s\n", rstrFileName.c_str());
iResult = -1;
}
}
if (iResult >= 0)
{
if (fwrite(pImageData, 1, (size_t)uiImageByteSize, pFile) != uiImageByteSize)
{
printf("Error writing Image Data to file %s\n", rstrFileName.c_str());
}
}
fclose(pFile);
}
else
{
printf("Error opening output file %s\n", rstrFileName.c_str());
}
}
int32_t CheckReferenceMetaData(FILE* pFile)
{
int32_t iResult;
size_t uiBytesRead;
uint32_t uiMetaSize;
uint32_t uiFileSize;
uint8_t uiMetaCheck[6];
iResult = -1;
fseek(pFile, 0L, SEEK_END);
uiFileSize = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
#if defined(_WIN32) || defined(_WINDOWS)
uiBytesRead = fread_s(uiMetaCheck, 6, 1, 6, pFile);
#else
uiBytesRead= fread(uiMetaCheck, 1, 6, pFile);
#endif
if (uiBytesRead == 6)
{
if ((uiMetaCheck[0] == 'M') && (uiMetaCheck[1] == 'e') && (uiMetaCheck[2] == 't') && (uiMetaCheck[3] == 'a'))
{
uiMetaSize = ((uint32_t)uiMetaCheck[4] & 0xFF) << 8;
uiMetaSize |= (uint32_t)uiMetaCheck[5] & 0xFF;
if (uiMetaSize < uiFileSize)
{
// looks like a valid file with meta data so seek past the meta data
iResult= 0;
fseek(pFile, uiMetaSize, SEEK_SET);
}
}
}
return(iResult);
}
// This is an example function to send HW Merge reference frames from RCD files created by the
// FLI Pilot application. It is provided as an example to help you
// extract the data from the RCD files for the FPRO_REFFRAMES structure required by the API.
int32_t SendHWMergeReferenceFiles(int32_t iHandle, char* pDSNUFileName, char* pPRNUFileName, uint32_t uiWidth, uint32_t uiHeight)
{
int32_t iResult;
FILE* pDSNUFile;
FILE* pPRNUFile;
FPRO_REFFRAMES refFrames;
uint32_t uiFrameSize;
size_t uiBytesRead;
iResult = -1;
// Open the files
pDSNUFile = NULL;
pPRNUFile = NULL;
#if defined(_WIN32) || defined(_WINDOWS)
fopen_s(&pDSNUFile, pDSNUFileName, "r+b");
fopen_s(&pPRNUFile, pPRNUFileName, "r+b");
#else
pDSNUFile= fopen(pDSNUFileName, "r+b");
pPRNUFile= fopen(pPRNUFileName, "r+b");
#endif
// Check the meta data and seek past it
iResult = CheckReferenceMetaData(pDSNUFile);
if (iResult >= 0)
iResult = CheckReferenceMetaData(pPRNUFile);
if (iResult >= 0)
{
// Set up the width and height- should be the full image size e.g. 4096 x 4096)
iResult = 0;
refFrames.uiWidth = uiWidth;
refFrames.uiHeight = uiHeight;
// Get space for the files
refFrames.pAdditiveLowGain = new int16_t[uiWidth * uiHeight];
refFrames.pAdditiveHighGain = new int16_t[uiWidth * uiHeight];
refFrames.pMultiplicativeLowGain = new uint16_t[uiWidth * uiHeight];
refFrames.pMultiplicativeHighGain = new uint16_t[uiWidth * uiHeight];
if ((refFrames.pAdditiveLowGain) && (refFrames.pAdditiveHighGain) &&
(refFrames.pMultiplicativeLowGain) && (refFrames.pMultiplicativeHighGain))
{
// Read the DSNU (additive) data
uiFrameSize = uiWidth * uiHeight * sizeof(uint16_t);
#if defined(_WIN32) || defined(_WINDOWS)
uiBytesRead = fread_s(refFrames.pAdditiveLowGain, uiFrameSize, 1, uiFrameSize, pDSNUFile);
#else
uiBytesRead= fread(refFrames.pAdditiveLowGain, 1, uiFrameSize, pDSNUFile);
#endif
if (uiBytesRead != uiFrameSize)
iResult = -1;
if (iResult >= 0)
{
// The high gain data starts immediately after the low gain data
#if defined(_WIN32) || defined(_WINDOWS)
uiBytesRead = fread_s(refFrames.pAdditiveHighGain, uiFrameSize, 1, uiFrameSize, pDSNUFile);
#else
uiBytesRead= fread(refFrames.pAdditiveHighGain, 1, uiFrameSize, pDSNUFile);
#endif
if (uiBytesRead != uiFrameSize)
iResult = -1;
}
// Read the PRNU (multiplicative) data
if (iResult >= 0)
{
#if defined(_WIN32) || defined(_WINDOWS)
uiBytesRead = fread_s(refFrames.pMultiplicativeLowGain, uiFrameSize, 1, uiFrameSize, pPRNUFile);
#else
uiBytesRead= fread(refFrames.pMultiplicativeLowGain, 1, uiFrameSize, pPRNUFile);
#endif
if (uiBytesRead != uiFrameSize)
iResult = -1;
}
if (iResult >= 0)
{
// The high gain data starts immediately after the low gain data
#if defined(_WIN32) || defined(_WINDOWS)
uiBytesRead = fread_s(refFrames.pMultiplicativeHighGain, uiFrameSize, 1, uiFrameSize, pPRNUFile);
#else
uiBytesRead= fread(refFrames.pMultiplicativeHighGain, 1, uiFrameSize, pPRNUFile);
#endif
if (uiBytesRead != uiFrameSize)
iResult = -1;
}
if (iResult >= 0)
{
// Finally we can call the API.....
iResult = FPROAlgo_SetHardwareMergeReferenceFrames(iHandle, &refFrames);
}
}
else
{
iResult = -1;
}
// give the memory back
if (refFrames.pAdditiveLowGain)
delete[]refFrames.pAdditiveLowGain;
if (refFrames.pAdditiveHighGain)
delete[]refFrames.pAdditiveHighGain;
if (refFrames.pMultiplicativeLowGain)
delete[]refFrames.pMultiplicativeLowGain;
if (refFrames.pMultiplicativeHighGain)
delete[]refFrames.pMultiplicativeHighGain;
if (pDSNUFile)
fclose(pDSNUFile);
if (pPRNUFile)
fclose(pPRNUFile);
}
return(iResult);
}
Finger Lakes Instrumentation Camera API.
LIBFLIPRO_API FPROAlgo_SetHardwareMergeEnables(int32_t iHandle, FPRO_HWMERGEENABLE mergeEnables)
Enable/disable hardware merging options.
LIBFLIPRO_API FPROSensor_GetCapabilityList(int32_t iHandle, uint32_t *pCapList, uint32_t *pNumCaps)
Retrieves the capabilities list for the connected camera.
LIBFLIPRO_API FPROCam_Open(FPRODEVICEINFO *pDevInfo, int32_t *pHandle)
Connects to the camera specified by the pDevInfo parameter.
LIBFLIPRO_API FPROCam_Close(int32_t iHandle)
Disconnects from the camera an releases the handle.
LIBFLIPRO_API FPROAlgo_SetHardwareMergeReferenceFrames(int32_t iHandle, FPRO_REFFRAMES *pRefFrames)
Sets the reference frames used in PCIE Fibre hardware image merging.
@ IFORMAT_RCD
FLI native RCD Frame.
Definition: libflipro.h:1351
@ FPROCAP_NUM
Number of supported capabilities.
Definition: libflipro.h:877
@ FPROCAP_MAX_PIXEL_WIDTH
Max allowed image width in pixels.
Definition: libflipro.h:860
@ FPROCAP_MAX_PIXEL_HEIGHT
Max allowed image height in pixels.
Definition: libflipro.h:861
LIBFLIPRO_API FPROFrame_GetVideoFrame(int32_t iHandle, uint8_t *pFrameData, uint32_t *pSize, uint32_t uiTimeoutMS)
Retrieves an image frame from the camera.
LIBFLIPRO_API FPROFrame_SetImageDataEnable(int32_t iHandle, bool bEnable)
Enables image data imaging.
LIBFLIPRO_API FPROFrame_ComputeFrameSize(int32_t iHandle)
Computes the size in bytes of the image frame.
LIBFLIPRO_API FPROCtrl_SetExposure(int32_t iHandle, uint64_t uiExposureTime, uint64_t uiFrameDelay, bool bImmediate)
Sets the exposure time of the image sensor.
@ HWMERGE_FRAME_BOTH
Normal merge, both low and high gain planes are corrected and merged.
Definition: libflipro.h:1565
LIBFLIPRO_API FPROFrame_CaptureStart(int32_t iHandle, uint32_t uiFrameCount)
Initiates the capture of the configured image.
LIBFLIPRO_API FPROFrame_SetImageArea(int32_t iHandle, uint32_t uiColOffset, uint32_t uiRowOffset, uint32_t uiWidth, uint32_t uiHeight)
Sets the area of the image sensor to be used to produce image frame data.
LIBFLIPRO_API FPROFrame_CaptureAbort(int32_t iHandle)
Aborts the active image capture.
LIBFLIPRO_API FPROCam_GetCameraList(FPRODEVICEINFO *pDeviceInfo, uint32_t *pNumDevices)
FPROCam_GetCameraList.
@ FPRO_CONNECTION_FIBRE
Camera is connected with a Fibre Optic link.
Definition: libflipro.h:200
Definition: libflipro.h:365
Definition: libflipro.h:1607
FPRO_IMAGE_FORMAT eMergeFormat
The image file format for the merged image. The Actual PCIE card only supports RCD and TIFF....
Definition: libflipro.h:1609
FPRO_HWMERGEFRAMES eMergeFrames
Specifies the frames to merge.
Definition: libflipro.h:1610
bool bMergeEnable
True if merging enabled. This must be true for the other enables to have any effect....
Definition: libflipro.h:1608
Definition: libflipro.h:1321
uint16_t * pMultiplicativeLowGain
Low Gain Multiply Reference Frame.
Definition: libflipro.h:1327
int16_t * pAdditiveHighGain
High Gain Additive Reference Frame.
Definition: libflipro.h:1326
int16_t * pAdditiveLowGain
Low Gain Additive Reference Frame.
Definition: libflipro.h:1325
uint32_t uiWidth
Width of the frames in pixels.
Definition: libflipro.h:1322
uint32_t uiHeight
Height of the frames in pixels.
Definition: libflipro.h:1323
uint16_t * pMultiplicativeHighGain
High Gain Multiply Reference Frame.
Definition: libflipro.h:1328