Polarization#

using Itala;
using Itala.GenApi;

/// <summary>
///  "Polarization" example shows how to process images containing light polarization data.
///  Polarization images are similar to bayer color images since they need to be demosaiced and
///  processed to determine the state of polarized light.
///  The following example shows a complete workflow for monochrome polarization images including
///  polarization components and Stokes vector computation. To get images like AoLP, DoLP and
///  intensity directly, a dedicated overload set is available.
/// </summary>
internal class Program
{
    const int ACQUIRE_COUNT = 50;

    const string INDENT = "\t";

    const string PIXEL_FORMAT = "Polarized00Mono8";

    private static void Polarization_Sample()
    {
        Console.WriteLine("######## Polarization ########");
        ISystem system = SystemFactory.Create();
        List<DeviceInfo> deviceInfos = system.EnumerateDevices();

        if (deviceInfos.Count == 0)
            throw new ItalaRuntimeException("No devices found. Example canceled.");
        if (deviceInfos[0].AccessStatus != DeviceAccessStatus.AvailableReadWrite)
            throw new ItalaRuntimeException("Target device is unaccessible in RW mode. Example canceled.");
        IDevice device = system.CreateDevice(deviceInfos[0]);
        Console.WriteLine("First device initialized.");

        INodeMap deviceNodeMap = device.GetNodeMap();

        // Set the pixelformat to Polarized00Mono8 or whatever format is available on the camera.
        IEnumeration pixelFormat = deviceNodeMap.GetNode<IEnumeration>("PixelFormat");
        if (!pixelFormat.IsWritable)
            throw new ItalaRuntimeException("Unable to configure the pixel format. Aborting.");
        Int64 originalPixelFormat = pixelFormat.IntValue;
        pixelFormat.FromString(PIXEL_FORMAT);
        Console.WriteLine("PixelFormat se to " + PIXEL_FORMAT);


        // Start a default continuous acquisition. Internally, the runtime allocates a
        // queue of 16 image buffers thus a maximum of 16 images can be grabbed simultaneously
        // without being released. An additional overload function allows to set the
        // buffer and frame count.
        device.StartAcquisition();
        Console.WriteLine("Acquisition started.");

        IImage image = device.GetNextImage(1000);

        // Clone the grabbed image for convenience so that it can be returned to the library and the
        // acquisition can be stopped.
        IImage polarizationImage = image.Clone() as IImage;
        image.Dispose();
        device.StopAcquisition();
        Console.WriteLine("Acquisition stopped.");

        // 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.
        // NearestNeighbour on Polarized00Mono8 produces Mono8 components.
        Console.WriteLine("Extracting all polarization components..");
        PolarComponents polarComponents = Polarization.ExtractAllPolarComponents(polarizationImage, PolarDemosaicingAlgorithm.NearestNeighbour);
        Console.WriteLine("P45 format is " + Pfnc.GetPixelFormatDescription(polarComponents.P45.PixelFormat));

        // 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.
        Console.WriteLine("Computing all stokes vectors..");
        StokesVectors stokesVectors = Polarization.ComputeAllStokes(polarComponents);
        Console.WriteLine("S0 format is " + Pfnc.GetPixelFormatDescription(stokesVectors.S0.PixelFormat));

        // 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.
        Console.WriteLine("Computing linear polarization images..");
        IImage dolpImage = Polarization.ComputeDoLP(stokesVectors);
        IImage aolpImage = Polarization.ComputeAoLP(stokesVectors);
        IImage intensityImage = Polarization.ComputeIntensity(stokesVectors, polarizationImage.PixelFormat);
        Console.WriteLine("DoLP format is " + Pfnc.GetPixelFormatDescription(dolpImage.PixelFormat));
        Console.WriteLine("AoLP format is " + Pfnc.GetPixelFormatDescription(aolpImage.PixelFormat));
        Console.WriteLine("Intensity format is " + Pfnc.GetPixelFormatDescription(intensityImage.PixelFormat));

        // 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.
        Console.WriteLine("Computing quadrants image..");
        IImage pQuadrantsImage = Polarization.ComputePolarQuadrantsImage(polarizationImage);
        Console.WriteLine("PolarQuadrants format is " + Pfnc.GetPixelFormatDescription(pQuadrantsImage.PixelFormat));

        // 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:
        Console.WriteLine("Computing DoLP without intermediate steps..");
        IImage directDolpImage = Polarization.ComputeDoLP(polarizationImage, PolarDemosaicingAlgorithm.NearestNeighbour);
        Console.WriteLine("directDoLP format is " + Pfnc.GetPixelFormatDescription(directDolpImage.PixelFormat));

        // Display or process DoLP

        // Restore the original pixel format value
        pixelFormat.IntValue = originalPixelFormat;

        dolpImage.Dispose();
        aolpImage.Dispose();
        intensityImage.Dispose();
        polarizationImage.Dispose();
        pQuadrantsImage.Dispose();
        directDolpImage.Dispose();
        stokesVectors.S0.Dispose();
        stokesVectors.S1.Dispose();
        stokesVectors.S2.Dispose();
        polarComponents.P0.Dispose();
        polarComponents.P45.Dispose();
        polarComponents.P90.Dispose();
        polarComponents.P135.Dispose();

        device.Dispose();
        Console.WriteLine("Device instance disposed.");
        system.Dispose();
        Console.WriteLine("System instance disposed.");
    }

    private static void Main(string[] args)
    {
        try
        {
            Polarization_Sample();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}