Overview
The SDK software package comes with a set of programming examples for C++.
Currently, there are four examples included:
Example | Description |
acquisition_basics | Demonstrates how to discover and open a device and how to acquire images. |
feature_iteration | Demonstrates how to iterate through the feature tree of a device and how to set / get features. |
calibration_generate | Demonstrates how to generate PRNU and DSNU calibration files and upload it to camera or to save it in local PC memory. |
save_rgb10and12 | Demonstrates on how to convert RGB10 and RGB12 pixelformat images into RGB8 or RGB16 bit images and save them in required image format. Supported image formats are (.png, .bmp. .tiff, .jpeg) |
Acquisition Basics
The aquesition_basics example shows how to discover and open a device, set features and acquire images.
Location
Windows: C:\Users\Public\Documents\Chromasens\GCT2\examples\basic
Linux: /usr/CSGenicam-SDK/share/csgenicam/examples/basic
#include <csi/csi.h>
#include "Acquisition.h"
#include <iostream>
#include <vector>
using namespace CSI;
void progressCB(const csiDiscoveryInfo* dis)
{
std::cout << "Discovery running: " << dis->progress << "%" << std::endl;
}
csiErr letUserChooseCamera(csiDeviceInfo& outDev)
{
csiErr result = csiErr::csiSuccess;
std::cout << std::endl;
// start device discovery
csiDiscoveryInfo discovery;
result = csiDiscoverDevices(&discovery, CSI::CSI_DEFAULT_DISCOVERY_TIME_MS, progressCB);
if (result != csiSuccess)
{
char errText[2056];
csiGetErrorDescription(result, errText, sizeof(errText));
std::cout << "Device discovery failed. Error: " << errText << std::endl;
return result;
}
if (discovery.numDevices == 0) {
std::cout << "No devices found." << std::endl;
return csiErr::csiNotFound;
}
std::vector<csiDeviceInfo> devices;
for (uint32_t deviceIndex = 0; deviceIndex < discovery.numDevices; deviceIndex++) {
csiDeviceInfo di;
result = csiGetDeviceInfo(deviceIndex, &di);
if(result == csiSuccess) {
devices.push_back(di);
}
}
if (devices.empty()) {
std::cout << "No acquisition device found!" << std::endl;
return csiErr::csiNotFound;
}
std::cout << "Number of acquisition devices found: " << devices.size() << std::endl;
std::cout << std::endl;
std::cout << "The following cameras have been found:" << std::endl;
int i = 0;
for (auto& currDev : devices) {
std::cout << i << ": ";
std::cout << currDev.name << " TL-name: " << currDev.tlProducerInfos.transportLayerName << " TL-Address: " << currDev.tlProducerInfos.transportLayerPath << " TL-Type: " << currDev.tlProducerInfos.transportLayerType << " Connected via: " << currDev.interfaceDescription << std::endl;
i++;
}
int cameraIndex = 0;
if (devices.size() > 1) {
std::cout << "Select device: ";
std::cin >> cameraIndex;
}
if (cameraIndex < 0 || cameraIndex >= devices.size()) {
std::cout << "Device not available!" << std::endl;
return csiErr::csiNotFound;
}
outDev = devices[cameraIndex];
return result;
}
int main(int argc, char** argv)
{
csiErr status;
// Initializing the SDK
status = csiInit(CSI::csiLogLevel::CSI_LOGLEVEL_TRACE);
if(status != csiSuccess) {
std::cout << "Failed to init library!" << std::endl;
return status;
}
csiDeviceInfo choosenDev;
status = letUserChooseCamera(choosenDev);
if(status != csiSuccess) {
std::cout << "Failed to select camera!" << std::endl;
return status;
}
csiHandle dev;
status = csiOpenDevice(choosenDev.deviceIdentifier,choosenDev.interfaceID, &dev, CSI::CSI_DEFAULT_DISCOVERY_TIME_MS, csiDeviceAccessMode::CSI_DEV_MODE_EXCLUSIVE);
if (status != csiSuccess) {
std::cout << "Failed to open camera! Error: " << status <<std::endl;
csiClose();
return status;
}
// Example for setting feature values into camera
int64_t width = 512;
if (csiSetFeatureInt(dev, "Width", width) == csiSuccess)
{
std::cout << "Width set to " << width << std::endl;
}
else {
std::cout << "Failed set Width feature!" << std::endl;
}
int64_t height = 512;
if(csiSetFeatureInt(dev, "Height", height) == csiSuccess)
{
std::cout << "Height set to " << height << std::endl;
}
else
{
std::cout << "Failed to set Height feature!" << std::endl;
}
std::cout << std::endl;
// Example for event based acquisition
std::cout << "Event based acquisition begins:" << std::endl;
csiErr result = startAcquisition(dev);
if (result == csiSuccess) {
std::cout << "Event based acquisition succeeds." << std::endl << std::endl;
}
else {
std::cout << "Event based acquisition fails." << std::endl << std::endl;
}
// Example for acquisition by calling the csiGetNextImage-function
std::cout <<"Acquisition directly by calling the csiGetNextImage function begins: " << std::endl;
result = startAcquisitionGetNextImg(dev);
if (result == csiSuccess) {
std::cout << "Acquisition directly by calling the csiGetNextImage function succeeds." << std::endl;
}
else {
std::cout << "Acquisition directly by calling the csiGetNextImage function fails." << std::endl;
}
csiCloseDevice(dev);
csiClose();
system("pause");
return 0;
}
Feature Iteration
The feature_iteration examples shows how to iterate through the feature tree of a device and set and get feature values.
Location
Windows: C:\Users\Public\Documents\Chromasens\GCT2\examples\feature_iteration
Linux: /usr/CSGenicam-SDK/share/csgenicam/examples/feature_iteration
////////////////////////////////////////////////////////////////////////////////////////
// Sample to demonstrate how to iterate through the whole feature tree of the device
// 1. Sample will let the user choose from the available transport layers in the system
// 2. If a device was found, it is opened
// 3. Using a recursive function the sample walks through the complete feature tree and
// prints its content to the console. The different subtrees are indicated by indenting
// one tab per level
// 4. Connection and API will be closed again
////////////////////////////////////////////////////////////////////////////////////////
#include <csi/csi.h>
#include <iostream>
#include <functional>
#include <memory.h>
#include <vector>
#include <string>
using namespace CSI;
void progressCB(const csiDiscoveryInfo* dis)
{
std::cout << "Discovery running: " << dis->progress << "%" << std::endl;
}
csiErr letUserChooseCamera(csiDeviceInfo& outDev)
{
csiErr result = csiErr::csiSuccess;
std::cout << std::endl;
// start device discovery
csiDiscoveryInfo discovery;
result = csiDiscoverDevices(&discovery, CSI_DEFAULT_DISCOVERY_TIME_MS, progressCB);
if (result != csiSuccess)
{
char errText[2056];
csiGetErrorDescription(result, errText, sizeof(errText));
std::cout << "Device discovery failed. Error: " << errText << std::endl;
return result;
}
if (discovery.numDevices == 0) {
std::cout << "No devices found." << std::endl;
return csiErr::csiNotFound;
}
std::vector<csiDeviceInfo> devices;
for (uint32_t deviceIndex = 0; deviceIndex < discovery.numDevices; deviceIndex++) {
csiDeviceInfo di;
result = csiGetDeviceInfo(deviceIndex, &di);
if(result == csiSuccess) {
devices.push_back(di);
}
}
if (devices.empty()) {
std::cout << "No acquisition device found!" << std::endl;
return csiErr::csiNotFound;
}
std::cout << "Number of acquisition devices found: " << devices.size() << std::endl;
std::cout << std::endl;
std::cout << "The following cameras have been found:" << std::endl;
int i = 0;
for (auto& currDev : devices) {
std::cout << i << ": ";
std::cout << currDev.name << " TL-name: " << currDev.tlProducerInfos.transportLayerName << " TL-Type: " << currDev.tlProducerInfos.transportLayerType << " Connected via: " << currDev.interfaceDescription << std::endl;
i++;
}
int cameraIndex = 0;
if (devices.size() > 1) {
std::cout << "Select device: ";
std::cin >> cameraIndex;
}
if (cameraIndex < 0 || cameraIndex >= devices.size()) {
std::cout << "Device not available!" << std::endl;
return csiErr::csiNotFound;
}
outDev = devices[cameraIndex];
return result;
}
void ReplaceChars(char * DestString, char * SearchString, char * ReplaceStr)
{
// Search forward.
char *pdest, *CharString;
int result = 0;
result = 0;
CharString = DestString + result;
pdest = strstr(CharString, SearchString);
while (pdest != NULL) {
result = (int)(pdest - CharString);
std::cout << DestString << ": " << SearchString << " found at position " << result << std::endl;
CharString[result] = ReplaceStr[0];
CharString = DestString + result;
pdest = strstr(CharString, SearchString);
}
if (result) {
std::cout << "New String: " << DestString << "\n+++++++++++++++++++++++++++++++++++\n" << std::endl;
}
}
#define NUM_FEAT 10000
std::string FeatStrings[NUM_FEAT];
int NumFeat = 0;
bool FeatStringAvailable (const char * SearchString )
{
// Search for "SearchString
for (int i = 0; i < NumFeat; i++)
{
int CompResult = FeatStrings[i].compare(SearchString);
if (0 == CompResult)
return true;
}
return false;
}
int main(int argc, char** argv)
{
csiErr status;
std::string tmp;
int FeatureOnlyOnce = 1;
const char * FeatureTypeArray[]
{
"CSI_UNKNOWN_TYPE",
"CSI_BOOLEAN_TYPE",
"CSI_INT_TYPE",
"CSI_FLOAT_TYPE",
"CSI_STRING_TYPE",
"CSI_ENUMERATION_TYPE",
"CSI_ENUMENTRY_TYPE",
"CSI_CATEGORY",
"CSI_COMMAND",
"CSI_REGISTER",
"CSI_PORT"
};
const char * FindChars[] =
{
"GainAutoAvailable",
"LUTDatasetNameAvailable",
"GevInterfaceBaseAddress"
};
int FindCharsCnt = 3;
// Initializing the SDK
status = csiInit(CSI::csiLogLevel::CSI_LOGLEVEL_TRACE);
if(status != csiSuccess) {
std::cout << "Failed to init library!" << std::endl;
return status;
}
csiDeviceInfo choosenDev;
status = letUserChooseCamera(choosenDev);
if(status != csiSuccess) {
std::cout << "Failed to select camera!" << std::endl;
return status;
}
csiHandle dev;
status = csiOpenDevice(choosenDev.deviceIdentifier, choosenDev.interfaceID, &dev, CSI_DEFAULT_DISCOVERY_TIME_MS, csiDeviceAccessMode::CSI_DEV_MODE_EXCLUSIVE);
if (status != csiSuccess) {
std::cout << "Failed to open camera! Error: " << status <<std::endl;
csiClose();
return status;
}
// Example for retrieving all available features from the camera
csiFeatureType featType;
csiFeatureParameter f_param;
int32_t lvl = 0, lastSaveLvl = 0;
// open file for CSV data
FILE *CSVFile, *LOGFile;
//const char * filename = "SWIR_GIGE.csv";
//const char * filename = "G8_DXGE.csv";
const char * filename = "Camera.csv";
int err;
size_t WriteLen;
errno_t error;
char LOGText[2048];
memset(LOGText, 0, sizeof(LOGText));
char Text[4096];
unsigned int textlen = 0, textmax = sizeof(Text);
#define TEXTREST ( (textlen>=textmax)? 0 : textmax - textlen )
#define TEXTLEN textlen = (unsigned int) strlen(Text);
Text[0] = 0;
err = fopen_s(&LOGFile, "LOGFile.txt", "w");
if (err = fopen_s(&CSVFile, filename, "w") != 0)
{
printf("open of Output file: %s failed!\n", filename);
printf("Press 'ENTER' to continue !!\n");
std::cout << "press enter to exit" << std::endl;
std::getline(std::cin, tmp);
return -1;
}
else
{
printf("Output file: %s successful opened!\n", filename);
error = strncat_s(Text, "Level;Name;Type;", TEXTREST); TEXTLEN
strncat_s(Text, "visibility; access;", TEXTREST); TEXTLEN
strncat_s(Text, "display Notation; representation; display precision;", TEXTREST); TEXTLEN
strncat_s(Text, "value Int; increment Int; minimum Int; maximumInt;", TEXTREST); TEXTLEN
strncat_s(Text, "value Float; increment Float; minimum Float; maximum Float;", TEXTREST); TEXTLEN
strncat_s(Text, "value String; maximum StringLength;", TEXTREST); TEXTLEN
strncat_s(Text, "Enum Counter; Enum Index;", TEXTREST); TEXTLEN
strncat_s(Text, "display Name; tooltip; isFeature;IsLittleEndian;", TEXTREST); TEXTLEN
strncat_s(Text, "value Unit; feature RegLength; feature RegAddress;", TEXTREST); TEXTLEN
strncat_s(Text, "\n", TEXTREST); TEXTLEN
WriteLen = fwrite(Text, textlen, 1, CSVFile);
}
// Walk recursively through the parameter tree
std::function<void(const char*, int32_t)> recursiveFeatureList = [&](const char* ft, int32_t lvl)
{
uint32_t index = 0;
csiErr error = csiSuccess;
char featName[CSI_INFO_STRING_BUFFER_SIZE];
int cmpResult = 0;
int checkLevel = 0;
while (1)
{
error = csiIterateFeatureTree(dev, ft, index++, featName, sizeof(featName), &featType);
for (int j = 0; j < FindCharsCnt; j++)
{
cmpResult = strcmp(ft, FindChars[j]);
if (cmpResult == 0)
break;
}
//if (lvl > 10)
//{
// checkLevel++;
//}
//if (cmpResult == 0)
//{
// checkLevel++;
//}
if (error != csiSuccess) {
sprintf_s(&LOGText[0], 2048 - strlen(LOGText), "csiIterateFeatureTree: %s level: %d, %I32d, featName: %d \n", ft, lvl, index - 1, error);
WriteLen = fwrite(LOGText, strlen(LOGText), 1, LOGFile);
break;
}
else {
sprintf_s(&LOGText[0], 2048 - strlen(LOGText), "csiIterateFeatureTree: %s level: %d, %I32d, featName: %s, type: %s \n", ft, lvl, index - 1, featName, FeatureTypeArray[featType]);
WriteLen = fwrite(LOGText, strlen(LOGText), 1, LOGFile);
}
if (featType == csiFeatureType::CSI_UNKNOWN_TYPE) {
sprintf_s(&LOGText[0], 2048 - strlen(LOGText), "CSI_UNKNOWN_TYPE: %s level: %d, %I32d, featName: %s, type: %s \n", ft, lvl, index - 1, featName, FeatureTypeArray[featType]);
WriteLen = fwrite(LOGText, strlen(LOGText), 1, LOGFile);
continue;
}
textlen = 0, textmax = sizeof(Text);
memset(Text, 0, sizeof(Text));
error = csiGetFeatureParameter(dev, featName, &f_param);
if (error)
{
std::cout << "Error getting feature parameter: " << featName << error << std::endl;
sprintf_s(&LOGText[0], 2048 - strlen(LOGText), "Error getting feature parameter: %s error: %d \n", featName, error);
WriteLen = fwrite(LOGText, strlen(LOGText), 1, LOGFile);
}
if (FeatStringAvailable(f_param.name))
{
sprintf_s(&LOGText[0], 2048 - strlen(LOGText), "++FeatStringAvailable++: %s, featName: %s, level: %d, %I32d \n", ft, f_param.name, lvl, index - 1);
WriteLen = fwrite(LOGText, strlen(LOGText), 1, LOGFile);
if (FeatureOnlyOnce)
{
continue;
}
}
else
{
FeatStrings[NumFeat] = f_param.name;
// sprintf_s(&FeatStrings[NumFeat], FeatStrings[NumFeat].max_size(), "%s;", f_param.name);
NumFeat++;
}
if (f_param.access > CSI::CSI_ACCESS_NOT_AVAILABLE)
{
// Only for display purposes. Indicate the subelements by indenting a tab
//for (int i = 0; i < lvl; i++) {
// std::cout << "\t";
//}
//std::cout << f_param.displayName << " " << lvl << index << std::endl;
char FindString [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
char FindChar[] = {10, 9, 0x3b};
char ReplChar [] = { 0x20, 0 };
for (int i = 0; i < 3; i++) {
FindString[0] = FindChar[i];
ReplaceChars(f_param.valueStr, FindString, ReplChar);
ReplaceChars(f_param.displayName, FindString, ReplChar);
ReplaceChars(f_param.name, FindString, ReplChar);
ReplaceChars(f_param.tooltip, FindString, ReplChar);
}
sprintf_s(&Text[textlen], TEXTREST, "%I32d;", lvl); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "%s;", f_param.name); TEXTLEN
//sprintf_s(&Text[textlen], TEXTREST, "%d;", index); TEXTLEN
//sprintf_s(&Text[textlen], TEXTREST, "%s;", featName); TEXTLEN
switch (featType) {
default:
case csiFeatureType::CSI_UNKNOWN_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "UNKNOWN;"); TEXTLEN
break;
case csiFeatureType::CSI_BOOLEAN_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "BOOLEAN;"); TEXTLEN
break;
case csiFeatureType::CSI_INT_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "INT;"); TEXTLEN
break;
case csiFeatureType::CSI_FLOAT_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "FLOAT;"); TEXTLEN
break;
case csiFeatureType::CSI_STRING_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "STRING;"); TEXTLEN
break;
case csiFeatureType::CSI_ENUMERATION_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "ENUM;"); TEXTLEN
break;
case csiFeatureType::CSI_ENUMENTRY_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "ENUMENTRY;"); TEXTLEN
break;
case csiFeatureType::CSI_CATEGORY:
sprintf_s(&Text[textlen], TEXTREST, "CATEGORY;"); TEXTLEN
break;
case csiFeatureType::CSI_COMMAND:
sprintf_s(&Text[textlen], TEXTREST, "COMMAND;"); TEXTLEN
break;
case csiFeatureType::CSI_REGISTER:
sprintf_s(&Text[textlen], TEXTREST, "REGISTER;"); TEXTLEN
break;
case csiFeatureType::CSI_PORT:
sprintf_s(&Text[textlen], TEXTREST, "PORT;"); TEXTLEN
break;
}
switch (f_param.visibility) {
default:
sprintf_s(&Text[textlen], TEXTREST, "UNKNOWN;"); TEXTLEN
break;
case csiFeatureVisibility::CSI_VISIBILITY_BEGINNER:
sprintf_s(&Text[textlen], TEXTREST, "BEGINNER;"); TEXTLEN
break;
case csiFeatureVisibility::CSI_VISIBILITY_EXPERT:
sprintf_s(&Text[textlen], TEXTREST, "EXPERT;"); TEXTLEN
break;
case csiFeatureVisibility::CSI_VISIBILITY_GURU:
sprintf_s(&Text[textlen], TEXTREST, "GURU;"); TEXTLEN
break;
case csiFeatureVisibility::CSI_VISIBILITY_DEVELOPER:
sprintf_s(&Text[textlen], TEXTREST, "DEVELOPER;"); TEXTLEN
break;
case csiFeatureVisibility::CSI_VISIBILITY_INVISIBLE:
sprintf_s(&Text[textlen], TEXTREST, "INVISIBLE;"); TEXTLEN
break;
}
switch (f_param.access) {
default:
case csiAccessMode::CSI_ACCESS_UNKNOWN:
sprintf_s(&Text[textlen], TEXTREST, "UNKNOWN;"); TEXTLEN
break;
case csiAccessMode::CSI_ACCESS_NOT_AVAILABLE:
sprintf_s(&Text[textlen], TEXTREST, "NOT_AVAILABLE;"); TEXTLEN
break;
case csiAccessMode::CSI_ACCESS_READ_ONLY:
sprintf_s(&Text[textlen], TEXTREST, "READ_ONLY;"); TEXTLEN
break;
case csiAccessMode::CSI_ACCESS_READ_WRITE:
sprintf_s(&Text[textlen], TEXTREST, "READ_WRITE;"); TEXTLEN
break;
case csiAccessMode::CSI_ACCESS_WRITE_ONLY:
sprintf_s(&Text[textlen], TEXTREST, "WRITE_ONLY;"); TEXTLEN
break;
}
switch (f_param.displayNotation) {
default:
sprintf_s(&Text[textlen], TEXTREST, "UNKNOWN;"); TEXTLEN
break;
case csiDisplayNotation::CSI_NOTATION_AUTOMATIC:
sprintf_s(&Text[textlen], TEXTREST, "AUTOMATIC;"); TEXTLEN
break;
case csiDisplayNotation::CSI_NOTATION_FIXED:
sprintf_s(&Text[textlen], TEXTREST, "FIXED;"); TEXTLEN
break;
case csiDisplayNotation::CSI_NOTATION_SCIENTIFIC:
sprintf_s(&Text[textlen], TEXTREST, "SCIENTIFIC;"); TEXTLEN
break;
}
switch (f_param.representation)
{
case csiRepresentation::CSI_REPRESENTATION_LINEAR:
sprintf_s(&Text[textlen], TEXTREST, "LINEAR;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_LOGARITHMIC:
sprintf_s(&Text[textlen], TEXTREST, "LOGARITHMIC;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_BOOLEAN:
sprintf_s(&Text[textlen], TEXTREST, "BOOLEAN;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_PURENUMBER:
sprintf_s(&Text[textlen], TEXTREST, "PURENUMBER;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_HEX:
sprintf_s(&Text[textlen], TEXTREST, "HEX;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_IP:
sprintf_s(&Text[textlen], TEXTREST, "IP;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_MAC:
sprintf_s(&Text[textlen], TEXTREST, "MAC;"); TEXTLEN
break;
case csiRepresentation::CSI_REPRESENTATION_UNDEFINED:
default:
sprintf_s(&Text[textlen], TEXTREST, "UNDEFINED;"); TEXTLEN
break;
}
sprintf_s(&Text[textlen], TEXTREST, "%d;", f_param.displayPrecision); TEXTLEN
switch (featType) {
default:
case csiFeatureType::CSI_UNKNOWN_TYPE:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;;;"); TEXTLEN
break;
case csiFeatureType::CSI_BOOLEAN_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "%I64d;%I64d;%I64d;%I64d;;;;;;;;;", f_param.valueInt, f_param.incrementInt, f_param.minimumInt, f_param.maximumInt); TEXTLEN
break;
case csiFeatureType::CSI_INT_TYPE:
sprintf_s(&Text[textlen], TEXTREST, "%I64d;%I64d;%I64d;%I64d;;;;;;;;;", f_param.valueInt, f_param.incrementInt, f_param.minimumInt, f_param.maximumInt); TEXTLEN
break;
case csiFeatureType::CSI_FLOAT_TYPE:
sprintf_s(&Text[textlen], TEXTREST, ";;;;%f;%f;%f;%f;;;;;", f_param.valueFlt, f_param.incrementFlt, f_param.minimumFlt, f_param.maximumFlt); TEXTLEN
break;
case csiFeatureType::CSI_STRING_TYPE:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;%s;%d;;;", f_param.valueStr, (int) f_param.maximumStringLength); TEXTLEN
break;
case csiFeatureType::CSI_ENUMERATION_TYPE:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;%I32u;%d;", f_param.enumCounter, f_param.enumIndex); TEXTLEN
break;
case csiFeatureType::CSI_ENUMENTRY_TYPE:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;;;"); TEXTLEN
break;
case csiFeatureType::CSI_CATEGORY:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;;;"); TEXTLEN
break;
case csiFeatureType::CSI_COMMAND:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;;;"); TEXTLEN
break;
case csiFeatureType::CSI_REGISTER:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;;;"); TEXTLEN
break;
case csiFeatureType::CSI_PORT:
sprintf_s(&Text[textlen], TEXTREST, ";;;;;;;;;;;;"); TEXTLEN
break;
}
sprintf_s(&Text[textlen], TEXTREST, "%s;", f_param.displayName); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "%s;", f_param.tooltip); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "%d;", f_param.isFeature); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "%d;", f_param.isLittleEndian); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "%s;", f_param.valueUnit); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "%d;", (int) f_param.featureRegLength); TEXTLEN
sprintf_s(&Text[textlen], TEXTREST, "0x%I64x;", f_param.featureRegAddress); TEXTLEN
strncat_s(Text, "\n", TEXTREST); TEXTLEN
WriteLen = fwrite(Text, textlen, 1, CSVFile);
textlen = 0, textmax = sizeof(Text);
memset(Text, 0, sizeof(Text));
if (cmpResult == 0)
{
continue;
}
if (!std::string(featName).empty()) {
// Call the csiIterateFeatureTree based on the current element
recursiveFeatureList(featName, lvl + 1);
}
else {
sprintf_s(&Text[textlen], TEXTREST, "empty;"); TEXTLEN
}
memset(featName, 0, sizeof(featName));
//WriteLen = fwrite(Text, textlen, 1, CSVFile);
//textlen = 0, textmax = sizeof(Text);
//memset(Text, 0, sizeof(Text));
}
if (lastSaveLvl < lvl) {
//strncat_s(Text, "\n", TEXTREST); TEXTLEN
//WriteLen = fwrite(Text, textlen, 1, CSVFile);
//textlen = 0, textmax = sizeof(Text);
//memset(Text, 0, sizeof(Text));
}
else {
if (lastSaveLvl > lvl) {
lastSaveLvl = lvl;
}
}
lastSaveLvl = lvl;
}
sprintf_s(&LOGText[0], 2048 - strlen(LOGText), "reduce lvl = %d, index=%d \n", lvl, index);
WriteLen = fwrite(LOGText, strlen(LOGText), 1, LOGFile);
};
recursiveFeatureList("Root", 0);
err = fclose(CSVFile);
err = fclose(LOGFile);
csiCloseDevice(dev);
csiClose();
std::cout << "press enter to exit" << std::endl;
std::getline(std::cin, tmp);
return 0;
}
Calibration gernerate
This examples shows how to generate a PRNU and DSNU calibration file and upload it to the camera or save it to in local PC memory.
Location
Windows: C:\Users\Public\Documents\Chromasens\GCT2\examples\calibration_generate
Linux: /usr/CSGenicam-SDK/share/csgenicam/examples/calibration_generate
#include <csi/csi.h>
#include "Calibration_Generator.h"
#include <iostream>
#include <vector>
/*
Application: Calibration_Generator: - To generate DSNU/PRNU calibration data and upload it to the camera or to save it in a file.
This demo will show ho to use the SDK functions for generating DSNU and PRNU calibrations for the Chromasens evo cameras
This demo will show how to use the SDK functions for generating DSNU and PRNU calibrations for the Chromasens allPIXA evo cameras
and evo based OEM systems (= application specific systems based on allPIXA evo technology)
You should follow the correct order to generate the calibrations. PRNU cannot be created if the camera does not have a valid DSNU calibration in memory!
The cameras are shipped already with a DSNU and PRNU calibration present, therefore it should be possible to start directly with the PRNU calibration.
To generate valid calibrations it is essential, that the image conditions fit to the selected calibration:
DSNU: No light should hit the image sensor. Switch of light and darken the camera lens
PRNU: Ideally a moving white target should be used in order to eliminate irregularities on the target
Precondition for getting the best results out of the DSNU and PRNU correction it, that the camera is set to the correct
operating point. This can be done by using the feature "GainAuto" set to "Once" or "Continuous". If your system is operated with the same
conditions as in the factory calibration at Chromasens (e.g. as it is an OEM system) this step can be skipped.
In order to do the calibration with images from the camera valid conditions must be present. this is the duty of the operator.
The calibration functions will not set the camera into free run or encoder mode. This is the responsibility of the user!
For more detailed information about the calibration procedure, please see our online documentation:
https://docs.chromasens.de
Input arguments:
-imgSrc - The source of the input image to generate calibration data from. "camera" for acquiring image from camera. "disc\ for loading image from PC memory
If disc, then a source image file path is mandatory. It should provided with the input argument "-srcImgFile".
-calib - The calibration data mode. The options are "DSNU" or "PRNU".
-LUT - LUT selector, to mention which LUT file the calibration data is uploaded to the camera. The options are "LUT1" or "LUT2".
-toCamera - To denote if the calibration data should be uploaded to the camera. The options are "0" or "1".
-toFile - To denote if the calibration data should be saved in the PC. The options are "0" or "1"
If enabled, the "-dstCalibFile" should be provided with a valid file path and valid file extension.
-srcImgFile - File path to the source image file to generate calibration data.
-dstCalibFile - File path to save the generated calibration file in the PC. The file type should match the calibration mode. Please use ".dsnu" and ".prnu" as file types.
-tlPath - Folder path that contains the additional TL(Transport layer) which can be used for discovering and connecting cameras
*/
using namespace CSI;
csiReferenceImgLoadMode imgLoadMode = CSI_ACQUIRE_REF_IMG_FROM_CAMERA;
CalibrationMode calibMode = DSNU_CALIBRATION;
csiCalibrationLUT LUTSelector = CSI_DSNU_LUT1;
bool uploadToCamera = false, saveToFile = false;
std::string srcImgFile = "";
std::string calibrationFile = "";
std::string LUTsel = "";
std::string additionalTLPath = "";
/// <summary>
/// Maps the enum values to the correct feature enum names
/// </summary>
/// <param name="LUTSel">
/// enum which indicates where the calibration should ba saved to and which kind of calibration should be done
/// </param>
/// <returns>
/// the name of the enum to use when communicationg with the camera
/// </returns>
std::string getLUTSelectorName(const csiCalibrationLUT &LUTSel){
std::string lutName;
switch (LUTSel){
case csiCalibrationLUT::CSI_DSNU_LUT1:
lutName = "DSNU_LUT1";
break;
case csiCalibrationLUT::CSI_DSNU_LUT2:
lutName = "DSNU_LUT2";
break;
case csiCalibrationLUT::CSI_PRNU_LUT1:
lutName = "PRNU_LUT1";
break;
case csiCalibrationLUT::CSI_PRNU_LUT2:
lutName = "PRNU_LUT2";
break;
default:
lutName = "";
break;
}
return lutName;
};
/// <summary>
/// -imgSrc - The source of the input image to generate calibration data from. "camera" for acquiring image from camera. "disc\ for loading image from PC memory
/// If disc, then a source image file path is mandatory. It should provided with the input argument "-srcImgFile".
/// -calib - The calibration data mode. The options are "DSNU" or "PRNU".
/// -LUT - LUT selector, to mention which LUT file the calibration data is uploaded to the camera. The options are "LUT1" or "LUT2".
/// -toCamera - To denote if the calibration data should be uploaded to the camera. The options are "0" or "1".
/// -toFile - To denote if the calibration data should be saved in the PC. The options are "0" or "1"
/// If enabled, the "-dstCalibFile" should be provided with a valid file path and valid file extension.
/// -srcImgFile - File path to the source image file to generate calibration data.
/// -dstCalibFile - File path to save the generated calibration file in the PC. The file type should match the calibration mode. Please use ".dsnu" and ".prnu" as file types.
/// -tlPath - Folder path that contains the additional TL(Transport layer) which can be used for discovering and connecting cameras
/// </summary>
/// <param name="argc"></param>
/// <param name="argv"></param>
/// <returns></returns>
int parseArguments(int argc, char** argv) {
if (argc > 1) {
for (int i = 1; i < argc; i++) {
if (std::string(argv[i]) == "-imgSrc") {
std::string imgSrcMode = std::string(argv[i + 1]);
if (imgSrcMode == "camera") {
imgLoadMode = CSI_ACQUIRE_REF_IMG_FROM_CAMERA;
} else if (imgSrcMode == "disc") {
imgLoadMode = CSI_LOAD_REF_IMG_FROM_DISC;
} else {
std::cout << "The provided source option to get source image is not correct. Please "
"select either \"camera\" or \"disc\"."
<< std::endl;
system("pause");
return -1;
}
}
if (std::string(argv[i]) == "-calib") {
std::string calibrationMode = std::string(argv[i + 1]);
if (calibrationMode == "DSNU") {
calibMode = DSNU_CALIBRATION;
} else if (calibrationMode == "PRNU") {
calibMode = PRNU_CALIBRATION;
} else {
std::cout << "The provided calibration option is not correct. Please select either "
"\"DSNU\" or \"PRNU\"."
<< std::endl;
system("pause");
return -1;
}
}
if (std::string(argv[i]) == "-LUT") {
LUTsel = std::string(argv[i + 1]);
}
if (std::string(argv[i]) == "-toCamera") {
std::string toCamera = std::string(argv[i + 1]);
if (toCamera == "0") {
uploadToCamera = false;
} else if (toCamera == "1") {
uploadToCamera = true;
}
else {
std::cout << "The provided upload calibration file to camera is not correct. Please select either "
"\"0\" or \"1\"."
<< std::endl;
std::cout << "Uploading calibration file to camera will not be done." << std::endl;
system("pause");
}
}
if (std::string(argv[i]) == "-toFile") {
std::string toFile = std::string(argv[i + 1]);
if (toFile == "0") {
saveToFile = false;
} else if (toFile == "1") {
saveToFile = false;
} else {
std::cout << "The provided save calibration file to file is not correct. Please select either \"0\" "
"or \"1\"."
<< std::endl;
std::cout << "Saving calibration file to PC will not be done." << std::endl;
system("pause");
}
}
if (std::string(argv[i]) == "-srcImgFile") {
srcImgFile = std::string(argv[i + 1]);
}
if (std::string(argv[i]) == "-dstCalibFile") {
calibrationFile = std::string(argv[i + 1]);
}
if (std::string(argv[i]) == "-tlPath") {
additionalTLPath = std::string(argv[i + 1]);
}
}
} else {
std::cout << "Please metioned the required input arguments for generating calibration data and to upload it to camera or save it in PC." << std::endl
<< "Example: -imgSrc camera -calib DSNU -LUT LUT1 -toCamera 1 -toFile 1 -srcImgFie \"/Documents/Temp/srcImg.tiff\" -dstCalibFile \"/Documents/Temp/DSNU.dsnu\" -tlPath \"/usr/CSGenICamSDK/share/CSGenICam/S2I_GenTL\""
<< std::endl
<< std::endl
<< "Arguments:" << std::endl
<< "-imgSrc - Options are \"camera\" or \"disc\"" << std::endl
<< "-calib - Options are \"DSNU\" or \"PRNU\"" << std::endl
<< "-LUT - The options are \"LUT1\" or \"LUT2\"" << std::endl
<< "-toCamera - The options are \"0\" or \"1\"" << std::endl
<< "-toFile - The options are \"0\" or \"1\"" << std::endl
<< "-srcImgFile - File path to the source image file to generate calibration data. Supports only images of .tiff format and rgb images." << std::endl
<< "-dstCalibFile - File path to save the generated calibration file in the PC. The file type should match the calibration mode. Please use \".dsnu\" and \".prnu\" as file types." << std::endl
<< "-tlPath - Folder path that contains the additional TL(Transport layer) which can be used for discovering and connecting cameras" << std::endl
<< std::endl;
system("pause");
return -1;
}
if (uploadToCamera && (LUTsel != "")) {
if (calibMode == DSNU_CALIBRATION) {
if (LUTsel == "LUT1") {
LUTSelector = CSI_DSNU_LUT1;
} else if (LUTsel == "LUT2") {
LUTSelector = CSI_DSNU_LUT2;
} else {
std::cout << "The provided LUT selector option is not correct. Please select either \"LUT1\" or \"LUT2\"." << std::endl;
system("pause");
return -1;
}
}
if (calibMode == PRNU_CALIBRATION) {
if (LUTsel == "LUT1") {
LUTSelector = CSI_PRNU_LUT1;
} else if (LUTsel == "LUT2") {
LUTSelector = CSI_PRNU_LUT1;
} else {
std::cout << "The provided LUT selector option is not correct. Please select either \"LUT1\" or \"LUT2\"." << std::endl;
system("pause");
return -1;
}
}
}
if ((imgLoadMode == CSI_LOAD_REF_IMG_FROM_DISC) && (srcImgFile == "")) {
std::cout << "A valid source image path should be provided when the \"-imgsrc\" is set as disc. Please provide a valid image file path in \"-srcImgFile\"."
<< std::endl;
system("pause");
return -1;
}
if (saveToFile) {
if (calibrationFile == "") {
std::cout << "A valid calibration file path should be provided when the \"-toFile\" option is set as 1. Please provide a valid calibration file path "
"in \"-dstCalibFile\"."
<< std::endl;
system("pause");
return -1;
}
auto fileType = calibrationFile.substr(calibrationFile.length() - 5);
if (calibMode == DSNU_CALIBRATION && (fileType != ".dsnu")) {
std::cout << "A calibration file to save DSNU data should be of file type \"*.dsnu\". The provided file type is" << fileType
<< "Please provide a valid file" << std::endl;
system("pause");
return -1;
}
if (calibMode == PRNU_CALIBRATION && (fileType != ".prnu")) {
std::cout << "A calibration file to save PRNU data should be of file type \"*.prnu\". The provided file type is" << fileType
<< "Please provide a valid file" << std::endl;
system("pause");
return -1;
}
}
return 0;
}
/// <summary>
/// Set up the conditions for generating a valid calibration
/// This parameter set is passed to the calibration generation function
/// </summary>
/// <returns>
/// The calbration structure
/// </returns>
csiCalibrationParams createCalibrationParams()
{
// This is the defintion of the image Area used for the Generation of the calibration values
int ystart = 0, roiHeight = 1000;
// depending on the sheet used for calibration it might be necessary to use
// extrapolation for the PRNU-generation. If the template does not cover the full
// field of view, extrapolation should be used
// If DSNU-calibration is done, the extrapolation values are not used
int extraPolationLeft = 0, extraPolationRight = 0, extrapolationWidth = 100;
unsigned int validFirstPixel = 4714; // Should be read from the camera -> "OffsetX"
int targetValue = 255; // Only valid for the PRNU. The PRNU-factors will be calculated in such a way, that
double brightness = 0.0, contrast = 1.0; // Default values, will be set after the PRNU calculation(Not DSNU)
bool enableROI = true, enableExtrapolationLeft = false, enableExtrapolationRight = false, improveCalculation = true;
csiCalibrationParams calibParam = { enableROI,
ystart,
roiHeight,
enableExtrapolationLeft,
enableExtrapolationRight,
extraPolationLeft,
extraPolationRight,
extrapolationWidth,
validFirstPixel,
targetValue,
improveCalculation,
contrast,
brightness};
return calibParam;
}
int main(int argc, char** argv)
{
csiErr status;
int ret = parseArguments(argc, argv);
if (ret != 0) {
return ret;
}
// Initializing the SDK
status = csiInit(CSI::csiLogLevel::CSI_LOGLEVEL_TRACE);
if (status != csiSuccess) {
std::cout << "Failed to init library!" << std::endl;
return status;
}
csiCalibrationParams calibParam = createCalibrationParams();
if(uploadToCamera){
status = generateAndUploadCalibrationDataToCamera(imgLoadMode, srcImgFile, calibMode, LUTSelector, calibParam, additionalTLPath);
if (status == csiSuccess) {
std::cout << "Successfully generated and uploaded calibration data into the camera into LUT: " << getLUTSelectorName(LUTSelector) << std::endl;
}else{
std::cout << "Error in generating and uploading calibration data into the camera. Error: " << status << std::endl;
return status;
}
}
if(saveToFile){
status = generateAndSaveCalibrationDataToFile(imgLoadMode, srcImgFile, calibMode, calibrationFile, calibParam, additionalTLPath);
if (status == csiSuccess) {
std::cout << "Successfully generated and saved calibration data into the camera into file: " << calibrationFile << std::endl;
}else{
std::cout << "Error in generating and saving calibration data into the file. Error: " << status << std::endl;
return status;
}
}
csiClose();
system("pause");
return 0;
}
Save rgb10 and 12
This examples demonstrates on how to convert RGB10 and RGB12 pixelformat images into RGB8 or RGB16 bit images and save them in required image format. Supported image formats are (.png, .bmp. .tiff, .jpeg).
Location
Windows: C:\Users\Public\Documents\Chromasens\GCT2\examples\save_rgb10and12
Linux: /usr/CSGenicam-SDK/share/csgenicam/examples/save_rgb10and12
#include <csi/csi.h>
#include "save_RGB10and12.h"
#include <iostream>
#include <vector>
#include <cstdlib>
using namespace CSI;
int main(int argc, char** argv)
{
std::string pixelFormat = "", bitsPerPixel = "", saveImgFormat = "";
int numImgs =10;
int imageScantimeout = 100; //Default values
csiErr status;
if (argc > 1) {
for (int i = 1; i < argc; i++) {
if (std::string(argv[i]) == "-p") {
pixelFormat = std::string(argv[i+1]);
if (!(pixelFormat == "RGB10" || pixelFormat == "RGB8" || pixelFormat == "RGB12" || pixelFormat == "RGBa10" || pixelFormat == "RGBa12")) {
std::cout << "The provided pixelformat is not supported by this application" << std::endl;
system("pause");
return -1;
}
}
if (std::string(argv[i]) == "-bpp") {
bitsPerPixel = std::string(argv[i + 1]);
if (!(bitsPerPixel == "8" || bitsPerPixel == "16")) {
std::cout << "The provided bits per pixel for saving the image is not supported by this application" << std::endl;
system("pause");
return -1;
}
}
if (std::string(argv[i]) == "-imgFormat") {
auto imgFormat = std::string(argv[i + 1]);
if (!(imgFormat == "png" || imgFormat == "jpeg" || imgFormat == "tiff" || imgFormat == "bmp")) {
saveImgFormat = ".tiff";
std::cout << "The provided image format to save the image is not supported by this application. The images will be saved in .tiff format" << std::endl;
} else if (imgFormat == "png") {
saveImgFormat = ".png";
} else if (imgFormat == "tiff") {
saveImgFormat = ".tiff";
} else if (imgFormat == "jpeg") {
saveImgFormat = ".jpeg";
} else if (imgFormat == "bmp") {
saveImgFormat = ".bmp";
}
}
if (std::string(argv[i]) == "-numImgs") {
numImgs = atoi(argv[i + 1]);
if (numImgs <= 0) {
std::cout << "The requested number of images value is not valid. Please enter value greatet than 0." << std::endl;
std::cout << "Now, 10 images will be scanned and saved by default." << std::endl;
numImgs = 10;
}
}
if (std::string(argv[i]) == "-timeout") {
imageScantimeout = atoi(argv[i + 1]);
if (imageScantimeout <= 0) {
std::cout << "The requested image scan timeout value is not valid. Please enter value greatet than 0." << std::endl;
std::cout << "Now, the timeout value of 100 milliseconds is set by default." << std::endl;
imageScantimeout = 100;
}
}
}
} else {
std::cout << "Please mention the required pixel format and final image format's bits per pixel(8 or 16 bit). Example: -p RGB12 -bpp 8 -imgFormat tiff" << std::endl;
std::cout << "Additionally you could also mention the number of images to be saved and image scan timeout value. Example -numImgs 100 -timeout 1000"<< std::endl;
system("pause");
return 0;
}
int ret = assessInputParameters(pixelFormat, bitsPerPixel, saveImgFormat);
if (ret != 0) {
return ret;
}
csiHandle dev;
csiErr result = initCSIandOpenCamera(dev);
if (result != csiSuccess) {
return result;
}
// Example for acquisition by calling the csiGetNextImage-function
std::cout <<"Acquisition directly by calling the csiGetNextImage function begins." << std::endl;
std::cout << "After Acquisition of images, they will be converted and saved in respective directory. " << std::endl;
result = acquireAndSaveImageFromDevice(dev, bitsPerPixel, saveImgFormat, pixelFormat, numImgs, imageScantimeout);
if (result == csiSuccess) {
std::cout << "Acquisition directly by calling the csiGetNextImage function succeeds." << std::endl;
}
else {
std::cout << "Acquisition directly by calling the csiGetNextImage function fails." << std::endl;
}
std::cout << "Disconnecting the device..... " << std::endl;
csiCloseDevice(dev);
csiClose();
system("pause");
return 0;
}
Visual Studio Example Projects
The Visual Studio projects for the two examples are also included in the SDK. These projects could the found the same location as stated above. These example projects could also be built with CMake. The following section explains how to build a project with CMake.
Build examples
To build the examples requires CMake version > v3.14 and a build environment. The steps to build the examples are the same for both Windows and Linux:
1) Open the CMake GUI and select the examples root directory as the source folder of your project. ("Where is the source code") 2) Next, select a directory where to generate the project files, should be somewhere outside the source tree. ("Where to build the binaries")
3) Press the “Configure” button. After the first configuration it is required to manually set the path to the CSGenICam CMake configuration files:
4) Press “Configure” again and “Generate” afterwards. The project is now configured and can be opened and built from the directory selected in “Where to build the binaries”. 5) If the generated project is to be opened in Visual Studio, please follow the step mentioned in previousection, to add the DLL search path for the application.