Polarization#


// Include ItalaApi
#include <stdio.h>
#include <stdlib.h>
#include "ItalaApiC/ItalaC.h"

#ifdef _WIN32
  #include <windows.h>
  #define SLEEP_MS(ms) Sleep(ms)
#else
  #include <unistd.h>
  #define SLEEP_MS(ms) usleep(ms * 1000)
#endif

#define INDENT "\t"
#define PIXEL_FORMAT "Polarized00Mono8"

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;
}

int main(int argc, char** argv) {
  printf("***** Polarization 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 (error) return ErrorManager(error);
  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 found is initialized.\n\n");

  H_NODEMAP hNodeMap = NULL;
  error = DEV_GetNodeMap(hDevice, &hNodeMap);
  if (error) return ErrorManager(error);

  H_NODE hNodePixelFormat = NULL;
  error = NODEMAP_GetNode(hNodeMap, "PixelFormat", &hNodePixelFormat);
  if (error) return ErrorManager(error);

  bool isReadable = false;
  error = IsNodeReadable(hNodePixelFormat, &isReadable);
  if (error) return ErrorManager(error);
  if (!isReadable) {
    printf("PixelFormat feature not available. Aborting.\n");
    return ItalaErrorError;
  }

  // Set the pixelformat to Polarized00Mono8 or whatever format is available on the camera.
  int64_t originalPixelFormat = 0;
  error = NODE_EnumerationGetIntValue(hNodePixelFormat, &originalPixelFormat);
  if (error) return ErrorManager(error);

  error = NODE_FromString(hNodePixelFormat, PIXEL_FORMAT);
  printf("PixelFormat set to %s\n", PIXEL_FORMAT);

  error = DEV_StartAcquisition(hDevice);
  if (error) return ErrorManager(error);
  printf("Acquisition started.\n\n");

  H_IMAGE hImage = NULL, hPolarizationImage = NULL;
  error = DEV_GetNextImage(hDevice, 1000, &hImage);
  if (error) return ErrorManager(error);

  // Clone the grabbed image for convenience so that it can be returned to the library and the
  // acquisition can be stopped.
  error = IMG_Clone(hImage, &hPolarizationImage);
  if (error) return ErrorManager(error);

  error = IMG_Dispose(hImage);
  hImage = NULL;
  if (error) return ErrorManager(error);

  error = DEV_StopAcquisition(hDevice);
  if (error) return ErrorManager(error);

  // Extract an image for each component (or angle) of the polarizer filter. Each resulting image
  // represents the captured light at 0, 45, 90 and 135 degrees respectively. Depending on the
  // demosaicing algorithm used, the pixel format of the resulting images can be of different types
  // (unsigned monochrome 8-bit or float).
  printf("Extracting all polarization components..\n");
  PolarComponents polarComponents;
  error = ExtractAllPolarComponents(hPolarizationImage, NearestNeighbour, &polarComponents);
  if (error) return ErrorManager(error);

  PfncFormat format;
  error = IMG_GetPixelFormat(polarComponents.P45, &format);
  if (error) return ErrorManager(error);
  printf("P45 format is %s\n", GetPixelFormatDescription(format));

  // display or process polarization components

  // Compute all the Stokes vectors to determine the polarization state of the light given the
  // intensities of the different polarizers on the sensor. Since we're dealing with linear
  // polarization data, only the first three (s0, s1 and s2) components of the vector are available.
  // Each resulting image represents the values of that particular component of the Stokes vector
  // across the whole sensor. For instance, the S0 image contains the s0 values of each pixel.
  printf("Computing all stokes vectors..\n");
  StokesVectors stokesVectors;
  error = ComputeAllStokes(&polarComponents, &stokesVectors);
  if (error) return ErrorManager(error);

  error = IMG_GetPixelFormat(stokesVectors.S0, &format);
  if (error) return ErrorManager(error);
  printf("S0 format is %s\n", GetPixelFormatDescription(format));

  // display or process the Stokes vectors

  // Given the stokes vectors, compute the linear polarization images.
  // The DoLP (Degree of Linear Polarization) image indicates the ratio of the intensity of the
  // polarized part of the light to the intensity of the unpolarized one. When the light is totally
  // polarized, this corresponds to the total intensity of the light. When the light is unpolarized,
  // this corresponds to zero.
  // The AoLP (Angle of Linear Polarization) image indicates the polarization direction of the
  // incoming light.
  // The intensity image simply indicate the total intensity of the incoming light.
  printf("Computing linear polarization images..\n");
  H_IMAGE hAolpImage = NULL, hDolpImage = NULL, hIntensityImage = NULL;

  error = ComputeAoLP(&stokesVectors, &hAolpImage);
  if (error) return ErrorManager(error);
  error = IMG_GetPixelFormat(hAolpImage, &format);
  if (error) return ErrorManager(error);
  printf("AoLP format is %s\n", GetPixelFormatDescription(format));

  error = ComputeDoLP(&stokesVectors, &hDolpImage);
  if (error) return ErrorManager(error);
  error = IMG_GetPixelFormat(hDolpImage, &format);
  if (error) return ErrorManager(error);
  printf("DoLP format is %s\n", GetPixelFormatDescription(format));

  error = IMG_GetPixelFormat(hPolarizationImage, &format);
  if (error) return ErrorManager(error);

  error = ComputeIntensity(&stokesVectors, Polarized00Mono8, &hIntensityImage);
  if (error) return ErrorManager(error);
  error = IMG_GetPixelFormat(hIntensityImage, &format);
  if (error) return ErrorManager(error);
  printf("Intensity format is %s\n", GetPixelFormatDescription(format));

  // display or process the images

  // From the source image, compute an image of the same size divided in four quadrants containing
  // the four polarization components.
  printf("Computing quadrants image..\n");
  H_IMAGE hQuadrantsImage = NULL;

  error = ComputePolarQuadrantsImage(hPolarizationImage, &hQuadrantsImage);
  if (error) return ErrorManager(error);
  error = IMG_GetPixelFormat(hQuadrantsImage, &format);
  if (error) return ErrorManager(error);
  printf("PolarQuadrants format is %s\n", GetPixelFormatDescription(format));

  // Display or process the quadrants image

  // If intermediate data like polar components or stokes vectors is not needed, monochrome AoLP,
  // DoLP and intensity can be directly computed with the dedicated functions given the polarized
  // image. For instance, DoLP:
  printf("Computing DoLP without intermediate steps..\n");
  H_IMAGE hDirectDolp = NULL;

  error = InstantComputeDoLP(hPolarizationImage, NearestNeighbour, &hDirectDolp);
  if (error) return ErrorManager(error);
  error = IMG_GetPixelFormat(hDirectDolp, &format);
  if (error) return ErrorManager(error);
  printf("DoLP format is %s\n", GetPixelFormatDescription(format));

  // Display or process DoLP

  // Restore the original pixel format value
  error = NODE_EnumerationSetIntValue(hNodePixelFormat, originalPixelFormat);
  if (error) return ErrorManager(error);

  // Each image MUST be disposed so that its memory is released. In real scenarios it's a good idea
  // to release the images as long as they're no longer required to keep the memory footprint low.
  // To prevent leaks, a dedicated set of functions is available in the Smart.h header.
  error = IMG_Dispose(hPolarizationImage);
  hPolarizationImage = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(polarComponents.P0);
  polarComponents.P0 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(polarComponents.P45);
  polarComponents.P45 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(polarComponents.P90);
  polarComponents.P90 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(polarComponents.P135);
  polarComponents.P135 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(stokesVectors.S0);
  stokesVectors.S0 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(stokesVectors.S1);
  stokesVectors.S1 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(stokesVectors.S2);
  stokesVectors.S2 = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(hAolpImage);
  hAolpImage = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(hDolpImage);
  hDolpImage = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(hIntensityImage);
  hIntensityImage = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(hQuadrantsImage);
  hQuadrantsImage = NULL;
  if (error) return ErrorManager(error);

  error = IMG_Dispose(hDirectDolp);
  hDirectDolp = NULL;
  if (error) return ErrorManager(error);

  printf("\nImage istances disposed.\n");

  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");
}