#include <stdio.h>
#include <stdlib.h>
#include "ItalaApiC/ItalaC.h"
#define ACQ_COUNT 10
#define MAX_PIXEL_DETECTED 1024
ItalaError ErrorManager(ItalaError e) {
size_t sizeMessage = 255;
char* message = (char*)malloc(sizeof(char) * sizeMessage);
ERR_GetLastErrorMessage(message, &sizeMessage);
printf("\nITALA ERROR (%d):\t%s, %zu char", ERR_GetLastErrorCode(), message, sizeMessage);
free(message);
return e;
}
ItalaError CorrectDetectedPixels(DefectivePixel* defectivePixel, size_t size, H_NODEMAP hNodeMap) {
ItalaError error = ItalaErrorSuccess;
// Start by setting the amount of pixel targeted for correction.
H_NODE hNodeOEDefectivePixelCount = NULL;
error = NODEMAP_GetNode(hNodeMap, "oeDefectivePixelCount", &hNodeOEDefectivePixelCount);
if (error) return ErrorManager(error);
bool isWritable = false;
error = IsNodeWritable(hNodeOEDefectivePixelCount, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to set the number of pixels to be corrected. Aborting.\n");
return ItalaErrorError;
}
error = NODE_IntegerSetValue(hNodeOEDefectivePixelCount, size);
if (error) return ErrorManager(error);
printf("\tCorrection procedure started with %zu pixels.\n", size);
// Get the pixel selector to iterate over the amount of targeted pixels.
H_NODE hNodeOEDefectivePixelSelector = NULL;
error = NODEMAP_GetNode(hNodeMap, "oeDefectivePixelSelector", &hNodeOEDefectivePixelSelector);
if (error) return ErrorManager(error);
error = IsNodeWritable(hNodeOEDefectivePixelCount, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to set the pixel selector for correction. Aborting.\n");
return ItalaErrorError;
}
// Get the features which allow to set the X and Y coordinate of the target pixel
// identified by the selector.
H_NODE hNodeOEDefectivePixelXCoordinate = NULL;
error =
NODEMAP_GetNode(hNodeMap, "oeDefectivePixelXCoordinate", &hNodeOEDefectivePixelXCoordinate);
if (error) return ErrorManager(error);
error = IsNodeWritable(hNodeOEDefectivePixelXCoordinate, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to set the X coordinate of the target pixel. Aborting.\n");
return ItalaErrorError;
}
H_NODE hNodeOEDefectivePixelYCoordinate = NULL;
error =
NODEMAP_GetNode(hNodeMap, "oeDefectivePixelYCoordinate", &hNodeOEDefectivePixelYCoordinate);
if (error) return ErrorManager(error);
error = IsNodeWritable(hNodeOEDefectivePixelYCoordinate, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to set the Y coordinate of the target pixel. Aborting.\n");
return ItalaErrorError;
}
// Set the coordinates of every targeted pixels.
for (size_t i = 0; i < size; i++) {
error = NODE_IntegerSetValue(hNodeOEDefectivePixelSelector, i);
if (error) return ErrorManager(error);
error = NODE_IntegerSetValue(hNodeOEDefectivePixelXCoordinate, defectivePixel[i].X);
if (error) return ErrorManager(error);
error = NODE_IntegerSetValue(hNodeOEDefectivePixelYCoordinate, defectivePixel[i].Y);
if (error) return ErrorManager(error);
printf("\tPixel [%jd, %jd] registered for correction. Was %s.\n", defectivePixel[i].X,
defectivePixel[i].Y, defectivePixel[i].TypeString);
}
// Once that the pixel map has been set (i.e. the amount of pixels to be corrected
// and their coordinates) the write function can be called to perform the
// correction.
H_NODE hNodeOEDefectivePixelWriteMap = NULL;
error = NODEMAP_GetNode(hNodeMap, "oeDefectivePixelWriteMap", &hNodeOEDefectivePixelWriteMap);
if (error) return ErrorManager(error);
error = IsNodeWritable(hNodeOEDefectivePixelWriteMap, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to write the pixel map to device memory. Aborting.\n");
return ItalaErrorError;
}
error = NODE_CommandExecute(hNodeOEDefectivePixelWriteMap);
if (error) return ErrorManager(error);
printf("\n\tCorrection command sent, procedure completed.\n");
return ItalaErrorSuccess;
}
int main(int argc, char** argv) {
printf("***** DefectivePixelCorrection example started. *****\n");
ItalaError error = ItalaErrorSuccess;
error = SYS_Initialize();
if (error) return ErrorManager(error);
size_t devicesInfoSize = 0;
error = SYS_EnumerateDevices(700);
if (error) return ErrorManager(error);
error = SYS_GetDeviceCount(&devicesInfoSize);
if (devicesInfoSize == 0) {
printf("No devices found. Example canceled.\n");
return ItalaErrorError;
}
DeviceInfo deviceInfo;
error = SYS_GetDeviceByIndex(0, &deviceInfo);
if (error) return ErrorManager(error);
if (deviceInfo.AccessStatus != AvailableReadWrite) {
printf("Target device is unaccessible in RW mode. Example canceled.\n");
return ItalaErrorError;
}
H_DEVICE hDevice = NULL;
error = SYS_CreateDevice(deviceInfo, &hDevice);
if (error) return ErrorManager(error);
printf("First device initialized.\n");
H_NODEMAP hNodeMap = NULL;
error = DEV_GetNodeMap(hDevice, &hNodeMap);
if (error) return ErrorManager(error);
// Start by setting a full resolution Mono8 image to perform the
// to perform the correction on the whole sensor. Keep the original
// values to restore the initial camera state at the end of the program.
// Width
H_NODE hNodeWidth = NULL;
NODEMAP_GetNode(hNodeMap, "Width", &hNodeWidth);
if (error) return ErrorManager(error);
bool isWritable = false;
error = IsNodeWritable(hNodeWidth, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to configure the image width. Aborting.\n");
return ItalaErrorError;
}
int64_t originalWidth = 0;
error = NODE_IntegerGetValue(hNodeWidth, &originalWidth);
if (error) return ErrorManager(error);
int64_t maxWidth = 0;
error = NODE_IntegerGetMax(hNodeWidth, &maxWidth);
if (error) return ErrorManager(error);
error = NODE_IntegerSetValue(hNodeWidth, maxWidth);
if (error) return ErrorManager(error);
printf("\tImage width set to %jd\n", maxWidth);
// Height
H_NODE hNodeHeight = NULL;
NODEMAP_GetNode(hNodeMap, "Height", &hNodeHeight);
if (error) return ErrorManager(error);
isWritable = false;
error = IsNodeWritable(hNodeHeight, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to configure the image height. Aborting.\n");
return ItalaErrorError;
}
int64_t originalHeight = 0;
error = NODE_IntegerGetValue(hNodeHeight, &originalHeight);
if (error) return ErrorManager(error);
int64_t maxHeight = 0;
error = NODE_IntegerGetMax(hNodeHeight, &maxHeight);
if (error) return ErrorManager(error);
error = NODE_IntegerSetValue(hNodeHeight, maxHeight);
if (error) return ErrorManager(error);
printf("\tImage height set to %jd\n", maxHeight);
// Pixel Format
H_NODE hNodePixelFormat = NULL;
NODEMAP_GetNode(hNodeMap, "PixelFormat", &hNodePixelFormat);
if (error) return ErrorManager(error);
isWritable = false;
error = IsNodeWritable(hNodePixelFormat, &isWritable);
if (error) return ErrorManager(error);
if (!isWritable) {
printf("Unable to configure the pixel format. Aborting.\n");
return ItalaErrorError;
}
int64_t originalPixelFormat = 0;
error = NODE_EnumerationGetIntValue(hNodePixelFormat, &originalPixelFormat);
if (error) return ErrorManager(error);
H_NODE hNodeEntryMono8 = NULL;
error = NODE_EnumerationGetEntryByName(hNodePixelFormat, "Mono8", &hNodeEntryMono8);
if (error) return ErrorManager(error);
int64_t mono8Format = 0;
error = NODE_EnumEntryGetValue(hNodeEntryMono8, &mono8Format);
if (error) return ErrorManager(error);
error = NODE_EnumerationSetIntValue(hNodePixelFormat, mono8Format);
if (error) return ErrorManager(error);
printf("\tPixelFormat set to Mono8.\n");
H_DEFECTDETECTION hDefDetMono8 = NULL;
error = CreateDefectDetection(maxWidth, maxHeight, D8Bit, &hDefDetMono8);
if (error) return ErrorManager(error);
error = DEV_StartAcquisition(hDevice);
if (error) return ErrorManager(error);
printf("\tAcquisition started.\n");
// Acquire the dark images needed for both leaky and hot/cold
// detection. The image data is accumulated thanks to the interface
// so that each image can be immediately disposed without wasting memory.
printf("\tAccumulating dark data..\n");
H_IMAGE hImage = NULL;
for (int i = 0; i < ACQ_COUNT; i++) {
error = DEV_GetNextImage(hDevice, 500, &hImage);
if (error) return ErrorManager(error);
void* dataImg;
error = IMG_GetData(hImage, &dataImg);
if (error) return ErrorManager(error);
// Accumulate the new dark image. Note that the function requires
// the raw data pointer, not the IImage itself!
error = DD_AccumulateDark(hDefDetMono8, (uint8_t*)dataImg);
if (error) return ErrorManager(error);
printf("\tImage %d added\n", i + 1);
error = IMG_Dispose(hImage);
hImage = NULL;
if (error) return ErrorManager(error);
}
// Acquire the gray images needed for hot/cold detection.
printf("\tAccumulating gray data..\n");
hImage = NULL;
for (int i = 0; i < ACQ_COUNT; i++) {
error = DEV_GetNextImage(hDevice, 500, &hImage);
if (error) return ErrorManager(error);
void* dataImg;
error = IMG_GetData(hImage, &dataImg);
if (error) return ErrorManager(error);
// Accumulate the new gray image. Note that the function requires
// the raw data pointer, not the IImage itself!
error = DD_AccumulateGray(hDefDetMono8, (uint8_t*)dataImg);
if (error) return ErrorManager(error);
printf("\tImage %d added\n", i + 1);
error = IMG_Dispose(hImage);
hImage = NULL;
if (error) return ErrorManager(error);
}
error = DEV_StopAcquisition(hDevice);
if (error) return ErrorManager(error);
printf("\tAcquisition stopped.\n");
// Find the leaky pixels of the sensor.
size_t leakyPixelSize = 0;
error = DD_FindLeaky(hDefDetMono8, MAX_PIXEL_DETECTED, 5);
if (error) return ErrorManager(error);
error = DD_GetLeakyCount(&leakyPixelSize);
if (error) return ErrorManager(error);
// Same for hot/cold pixels.
size_t hotNColdPixelSize = 0;
error = DD_FindHotNCold(hDefDetMono8, MAX_PIXEL_DETECTED, 5);
if (error) return ErrorManager(error);
error = DD_GetHotNColdCount(&hotNColdPixelSize);
if (error) return ErrorManager(error);
printf("%zu leaky pixels found.\n", leakyPixelSize);
printf("%zu hot/cold pixels found.\n", hotNColdPixelSize);
// Leaky and hot/cold pixels are equally defective for the purposes of
// the correction algorithm. Create a unique array and retrive the pixels.
// Perform the correction with the dedicated GenICam nodes.
size_t totDefectPixel = leakyPixelSize + hotNColdPixelSize;
DefectivePixel* defectivePixels =
(DefectivePixel*)malloc(sizeof(DefectivePixel) * totDefectPixel);
for (size_t i = 0; i < leakyPixelSize; i++) {
error = DD_GetLeakyByIndex(i, &defectivePixels[i]);
if (error) return ErrorManager(error);
}
for (size_t i = 0; i < hotNColdPixelSize; i++) {
error = DD_GetHotNColdByIndex(i, &defectivePixels[leakyPixelSize + i]);
if (error) return ErrorManager(error);
}
error = CorrectDetectedPixels(defectivePixels, totDefectPixel, hNodeMap);
if (error) return ErrorManager(error);
error = DD_Dispose(hDefDetMono8);
hDefDetMono8 = NULL;
if (error) return ErrorManager(error);
printf("\nMono8 detection instance disposed.\n");
error = NODE_IntegerSetValue(hNodeWidth, originalWidth);
if (error) return ErrorManager(error);
error = NODE_IntegerSetValue(hNodeHeight, originalHeight);
if (error) return ErrorManager(error);
error = NODE_EnumerationSetIntValue(hNodePixelFormat, originalPixelFormat);
if (error) return ErrorManager(error);
error = DEV_Dispose(hDevice);
hDevice = NULL;
if (error) return ErrorManager(error);
printf("Device instance disposed.\n");
error = SYS_Dispose();
if (error) return ErrorManager(error);
printf("System instance disposed.\n");
return 0;
}