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