/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Example.LFR.CS.BasicB
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Example.LFR.CS.BasicB
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// The application's main form.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public partial class MainForm : Form
{
// The CUDA compute instance.
Rx.LFR.Net.CudaCompute m_xCudaCompute;
// The view handle for the color coded depth image
int m_iViewHandle;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Default constructor.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public MainForm()
{
InitializeComponent();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Called by MainForm for shown events.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void MainForm_Shown(object sender, EventArgs e)
{
try
{
// Authenticate the light field runtime
Rx.LFR.Net.LightFieldRuntime.Authenticate();
// Enumerate all CUDA devices at the beginning
Rx.LFR.Net.Cuda.EnumerateCudaDevices();
// Assign the CUDA device and the calibration
m_xCudaCompute = new Rx.LFR.Net.CudaCompute();
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.PreProc_DataType, (uint) Rx.InteropNet.Runtime28.EDataType.UByte);
if (Rx.LFR.Net.Cuda.GetDeviceCount() == 0)
{
throw new Exception("No Cuda device found");
}
m_xCudaCompute.SetCudaDevice(Rx.LFR.Net.Cuda.GetDevice((int) 0));
// Preprocess parameter
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.PreProc_Sharp1_Enable, 1U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.PreProc_Sharp1_BlurStdDev, 2.5);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.PreProc_Sharp1_Factor, 1.8);
// Depth algorithm parameter
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_MinStdDeviation, 0.05);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_MinCorrelation, 0.9);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_PatchDiameter, 3U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_PatchStride, 2U);
// Depth fill parameter
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_Enabled, 1U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_IterCnt, 4U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_IterSize, 1U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_Complete, 1U);
// Depth Fill Bilateral denoise filter
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_Bilateral_Enabled, 1U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_Bilateral_FilterRadius, 5U);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_Bilateral_Edge, 0.1);
m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Depth_Fill_Bilateral_Range, 5.0);
// Init the CLUViz control
CLUViz.Net.Tool.Init();
// Create the view image
m_iViewHandle = CLUViz.Net.Tool.CreateViewImage(0, 0, 1000, 800, "Color Coded Depth Image");
}
catch (Rx.Net.RxException xEx)
{
throw new Exception(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Load an ray image.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void buttonLoadImage_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Ray Image|*.ray";
DialogResult diagRes = openFileDialog.ShowDialog();
if (diagRes == DialogResult.OK)
{
Rx.LFR.Net.RayImage xRayImg = new Rx.LFR.Net.RayImage();
// Read the ray file
Rx.LFR.Net.RayFileReader.Read(openFileDialog.FileName, xRayImg);
// Upload the new image to the compute class and apply the calibration
m_xCudaCompute.ApplyCalibration(xRayImg.GetCalibration(), true);
m_xCudaCompute.UploadRawImage(xRayImg);
buttonCalculateDepth.Enabled = true;
buttonCalculateDistance.Enabled = false;
}
}
catch (Rx.Net.RxException xEx)
{
throw new Exception(xEx.ToString());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Calculate depth.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void buttonCalculateDepth_Click(object sender, EventArgs e)
{
// Compute depth and total focus images.
m_xCudaCompute.Compute_PreProcess();
m_xCudaCompute.Compute_DepthRay();
m_xCudaCompute.Compute_DepthMap(Rx.LFR.Net.ESpace.View_Object_Pinhole);
m_xCudaCompute.Compute_Depth3D();
m_xCudaCompute.Compute_DepthColorCode(Rx.LFR.Net.ESpace.View_Object_Pinhole);
m_xCudaCompute.Compute_TotalFocus(Rx.LFR.Net.ESpace.View_Object_Pinhole);
// Get the image access interface. This interface allows:
// * Download CUDA image into host memory
// * Upload a host image to CUDA to overwrite a certain CUDA image
// * Access to CUDA device pointer to do own CUDA image processing
Rx.LFR.Net.ICudaDataImages xImages = (m_xCudaCompute.GetInterface(Rx.LFR.Net.Interfaces.ECudaCompute.Images)) as Rx.LFR.Net.ICudaDataImages;
// Download the color coded depth image
using (Rx.Net.Image xImgDepthMapColor = new Rx.Net.Image())
{
xImages.Download(Rx.LFR.Net.EImage.DepthMapColored_View_Object_Pinhole, xImgDepthMapColor);
// Display the color coded depth image
CLUViz.Net.Tool.ViewSetImage(m_iViewHandle, xImgDepthMapColor);
}
buttonCalculateDepth.Enabled = false;
buttonCalculateDistance.Enabled = true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Event handler. Calculate the distance between two points.
///
///
/// Source of the event.
/// Event information.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void buttonCalculateDistance_Click(object sender, EventArgs e)
{
// Calculate and show the distance.
double dDistance = Distance(10, 15, 100, 120);
labelDistance.Text = String.Format("Distance between point (10,15) and point (100,200): {0:F2} mm", dDistance);
buttonCalculateDistance.Enabled = false;
buttonLoadImage.Enabled = true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Evaluate distance between two points in object space.
///
///
/// x coordinate 1.
/// y coordinate 1.
/// x coordinate 2.
/// y coordinate 2.
///
/// The distance
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public unsafe double Distance(int iX1, int iY1, int iX2, int iY2)
{
// Get the image access interface. This interface allows:
// * Download CUDA image into host memory
// * Upload a host image to CUDA to overwrite a certain CUDA image
// * Access to CUDA device pointer to do own CUDA image processing
Rx.LFR.Net.ICudaDataImages xImages = (m_xCudaCompute.GetInterface(Rx.LFR.Net.Interfaces.ECudaCompute.Images)) as Rx.LFR.Net.ICudaDataImages;
// Download the color coded depth image
Rx.Net.Image xImgDepth3D = new Rx.Net.Image();
xImages.Download(Rx.LFR.Net.EImage.Depth3D, xImgDepth3D);
double dDistance = 0.0;
// Get an unsafe pointer to native memory where the image is held.
float* pData = (float*) xImgDepth3D.GetDataPtr();
int iWidth = xImgDepth3D.Format.Width;
int iPos1 = 4 * ((iY1 * iWidth) + iX1);
int iPos2 = 4 * ((iY2 * iWidth) + iX2);
float dX1 = pData[iPos1 + 0];
float dY1 = pData[iPos1 + 1];
float dZ1 = pData[iPos1 + 2];
float dX2 = pData[iPos2 + 0];
float dY2 = pData[iPos2 + 1];
float dZ2 = pData[iPos2 + 2];
float dDX = dX2 - dX1;
float dDY = dY2 - dY1;
float dDZ = dZ2 - dZ1;
dDistance = System.Math.Sqrt((double) (dDX * dDX + dDY * dDY + dDZ * dDZ));
return dDistance;
}
}
}