///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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.CameraA ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// namespace Example.LFR.CS.CameraA { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// The application's main form. /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class MainForm : Form { // The CLUViz Control instance CLUViz.Net.ViewCtrl m_xCluView; // The CLUViz Engine instance CLUViz.Net.EngineCtrl m_xCluEngine; // Flag that signalizes if the camera is currently stopped bool m_bFirstImageOfCamera; // The CUDA compute instance. Rx.LFR.Net.CudaCompute m_xCudaCompute; // The open GL interop instance that holes the open GL context Rx.LFR.Net.OpenGlInterop m_xOpenGlInterop; // The camera buffers. Rx.LFR.Net.ImageQueue m_xCamBuffer; // The camera server class that is able to find attached cameras. Rx.LFR.Net.CameraServer m_xCamServer; // true to stop process thread. bool m_bStopThread; // true if camera stopped. bool m_bCameraStopped; // index of the currently open camera uint m_uiCamIndex; // The focus plane. double m_dFocusPlane; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Default constructor. /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public MainForm() { InitializeComponent(); // Initialize the slider trackBarFocus.Enabled = true; // Set the starting slider value (0.5) and its range [0.0,1.0]. trackBarFocus.Minimum = 0; trackBarFocus.Maximum = 100; trackBarFocus.Value = 50; trackBarFocus.SmallChange = 1; // Add an event handler to the Scroll event, so that we can react to it trackBarFocus.Scroll += new System.EventHandler(this.trackBar_Scroll); // Flag to stop the thread m_bStopThread = false; // Init m_bCameraStopped = true; m_bFirstImageOfCamera = true; // Focus plane position m_dFocusPlane = 0.5; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void trackBar_Scroll(object sender, EventArgs e) { try { // Refocus from raw image UpdateFocus(); } catch (Rx.Net.RxException xEx) { MessageBox.Show(xEx.ToString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Executes the status action. /// /// /// Source for the. /// The message. /// Source for the. /// The message. /// Zero-based index of the value. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OnStatus(Rx.LFR.Net.EStatusMsgSrc eSource, Rx.LFR.Net.EStatusMsg eMsg, string sSource, string sMessage, int iValue) { // Print the status message Console.WriteLine("[{0}] {1, " + iValue * 4 + "}", sSource, sMessage); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Event handler. Called by MainForm for shown events. /// /// /// Source of the event. /// Event information. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void MainForm_Shown(object sender, EventArgs e) { try { /************************************************************************/ /* Prepare Visualization */ /************************************************************************/ // Start the CLU engine m_xCluEngine = new CLUViz.Net.EngineCtrl(); m_xCluEngine.Start(); // Now create the CLU control and embed it into the "panelClu" control. // Changes in size and position of panelClu are automatically applied // to the CLU control. // Since the CLU control display runs in a separate thread, we must // create an OpenGL rendering context for the CUDA thread (this thread) // that shares its texture memory with the OpenGL rendering context in // the CLU control thread. This is done automatically by setting the second // parameter to "true". m_xCluView = new CLUViz.Net.ViewCtrl(true, 0); /************************************************************************/ /* Initialize Camera and Cuda usage */ /************************************************************************/ // Initialize the open GL interop instance m_xOpenGlInterop = new Rx.LFR.Net.OpenGlInterop(); // Authenticate the light field runtime Rx.LFR.Net.LightFieldRuntime.Authenticate(); /// Initialize the calibration manager. Rx.LFR.Net.CalibrationManager.Initialize(); // 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); // Throw exception when no Cuda device has been found if (Rx.LFR.Net.Cuda.GetDeviceCount() == 0) { throw new Exception("No Cuda device found"); } // Set the Cuda device with index 0. This Example uses only one Cuda device m_xCudaCompute.SetCudaDevice(Rx.LFR.Net.Cuda.GetDevice((int) 0)); // Add the CluView to the panel panelClu.Controls.Add(m_xCluView); m_xCluView.Dock = DockStyle.Fill; // Add a status message callback if you are interested in status messages sent by the camera server while finding cameras m_xCamServer = new Rx.LFR.Net.CameraServer(); m_xCamServer.StatusMessage += OnStatus; // Start to find cameras. This is an synchronous call and we wait here until the find process has been finished m_xCamServer.FindCameras(); /************************************************************************/ /* Initialize Buffer */ /************************************************************************/ uint uBufferSize = 3; bool bOverwrite = false; // Create buffer within the given size and with the given overwrite flag m_xCamBuffer = new Rx.LFR.Net.ImageQueue(); m_xCamBuffer.Initialize(uBufferSize, bOverwrite); // Quit the application if there is no camera if (m_xCamServer.GetCameraCount() == 0) { Console.Write("No camera found\n"); return; } /************************************************************************/ /* Prepare GUI */ /************************************************************************/ // Add the CluView to the panel panelClu.Controls.Add(m_xCluView); m_xCluView.Dock = DockStyle.Fill; // Now set the visualization CLUScript from the resources. m_xCluView.SetScript(Example.LFR.CS.CameraA.Properties.Resources.View_Image_01); // Add all cameras to the combo box control if (m_xCamServer.GetCameraCount() > 0) { for (uint uCameraIndex = 0; uCameraIndex < m_xCamServer.GetCameraCount(); uCameraIndex++) { // Get the camera from our camera server Rx.LFR.Net.Camera xCamera = m_xCamServer.GetCamera(uCameraIndex); // Open the camera. This prepares the communication with the camera and checks the connection of GigE cameras // This does NOT start the camera stream xCamera.Open(); // Add a image captured callback. This method gets called for every captured camera image and more details are given there xCamera.ImageCaptured += OnImageCaptured; // If there is one image buffer per camera set the view caption to the camera name; string sCameraName = Rx.LFR.Net.CalibrationManager.GetCameraName(xCamera); string sCameraSerial = Rx.LFR.Net.CalibrationManager.GetCameraSerial(xCamera); // The camera name CBCameras.Items.Add(sCameraSerial + "- SN: " + sCameraName); } CBCameras.SelectedIndex = 0; m_uiCamIndex = 0; CBCameras.Enabled = true; // Start the selected camera StartCamera(); // Start the processing thread System.Threading.Thread xThread = new System.Threading.Thread(ProcessImage); xThread.Start(); } else { // No cameras found CBCameras.Items.Add("No Cameras found!"); CBCameras.SelectedIndex = 0; m_uiCamIndex = 0; CBCameras.Enabled = false; butStartVideo.Enabled = false; } } catch (Rx.Net.RxException xEx) { MessageBox.Show(xEx.ToString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Event handler. Called by MainForm for form closing events. /// /// /// Source of the event. /// Form closing event information. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { try { // Stop the Camera m_xCamServer.GetCamera(m_uiCamIndex).Stop(); // Clear the image buffer m_xCamBuffer.Clear(); // Stop the thread m_bStopThread = true; // End the CLU engine. This closes all CLU controls m_xCluEngine.End(); // Finalize the Lightfield Runtime. This frees all internal memory also on the CUDA device. Rx.LFR.Net.LightFieldRuntime.End(); } catch (Rx.Net.RxException xEx) { MessageBox.Show(xEx.ToString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Executes the image captured action. /// /// /// The image. /// The camera index. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OnImageCaptured(Rx.LFR.Net.ConstImage xConstImage, uint uCameraIndex) { /************************************************************************/ /* Image Captured */ /************************************************************************/ // ATTENTION: // All processing done in this callback would prevents the camera from capturing the next image. // Therefore it's advisable to BUFFER the image here and to process it in another thread. /************************************************************************/ /* Write into buffer */ /************************************************************************/ if (!m_xCamBuffer.CopyIn(xConstImage)) { // Buffer is full and overwrite is disabled // This is a lost frame return; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Process the image. /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ProcessImage() { // As long as this application is not stopped while (!m_bStopThread) { try { // Assume that the image queue is empty bool bQueueEmpty = true; // Wait for the image buffer to be not empty if (!m_xCamBuffer.WaitForNotEmpty(1000)) { // If the image queue is empty and the camera is not stopped continue if (!m_bCameraStopped) { continue; } } else { bQueueEmpty = false; } // If the queue is not empty get the new image from the queue else compute the refocus image on the last uploaded image if (!bQueueEmpty) { // Get the first image in the Queue Rx.Net.Image xImage = new Rx.Net.Image(); if (!m_xCamBuffer.MoveOut(xImage)) { // Wait again! This functions says that it waits until a frame is available continue; } // Upload the captured image as the new raw image of all further CUDA computations m_xCudaCompute.UploadRawImage(xImage); // Calculate the desired images m_xCudaCompute.Compute_PreProcess(); } // Set the new refocus parameter m_xCudaCompute.GetParams().SetValue(Rx.LFR.Net.Params.ECudaCompute.Focus_RelativeFocusPlane, m_dFocusPlane); // Calculate refocus image m_xCudaCompute.Compute_RefocusBasic(); // Get the texture access interface. This interface allows: // * Updating the texture. Rx.LFR.Net.ICudaDataTextures xTexture = (m_xCudaCompute.GetInterface(Rx.LFR.Net.Interfaces.ECudaCompute.Textures)) as Rx.LFR.Net.ICudaDataTextures; // Make the context shared in this thread if (m_bFirstImageOfCamera) { // We now have to make this shared rendering context current, // since otherwise all CUDA commands will fail. That is, // CUDA is only initialized once this rendering context is made current. // Note that the shared rendering context for this thread is attached to // an invisible dummy window that is held internally. m_xCluView.MakeCurrentSharedRC(); // Store the current context m_xOpenGlInterop.StoreCurrentContext(); } // Update texture stored in the open GL interop instance with the given image id. xTexture.UpdateTexture(Rx.LFR.Net.EImage.RefocusBasic, m_xOpenGlInterop); if (m_bFirstImageOfCamera) { // 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; // Create an image format if it is the first image Rx.Net.ImageFormat xImgF = xImages.GetImageFormat(Rx.LFR.Net.EImage.RefocusBasic); // Initialize the CLUScript variables iWidth and iHeight with // the dimensions of the refocused image. m_xCluView.SetVarNumber("iWidth", xImgF.Width); m_xCluView.SetVarNumber("iHeight", xImgF.Height); // Execute the script with ToolName == "Image_Create". // This prepared the image view for an image of the given size. // The image itself is not copied at this point. m_xCluView.ExecScript("Image_Create"); // Get the texture id uint uiTexID = m_xOpenGlInterop.GetTextureID(Rx.LFR.Net.EImage.RefocusBasic); // Set the id to the CluView script m_xCluView.SetVarNumber("texImage", (int) uiTexID); // If the refocused image is of luminance type, we need to select // a different shader for the image display. if (((xImgF.PixelType == Rx.InteropNet.Runtime28.EPixelType.Lum) || (xImgF.PixelType == Rx.InteropNet.Runtime28.EPixelType.LumA))) { m_xCluView.ExecScript("Image_Lum_Enable"); } } // The first image has been captured for this camera m_bFirstImageOfCamera = false; // Tell the CLU control to redraw the current scene tree. // This does not re-execute the script itself. // It needs to be called to ensure that the new content of // the image texture is displayed. m_xCluView.Update(); } catch (Rx.Net.RxException ex) { Console.WriteLine("\n\n\nOnImageCaptured Exception:\n\n\n{0}\n\n\n", ex.ToString(true)); System.Environment.Exit(-1); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Update the focus setting and compute the refocus image again with the new parameter. /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void UpdateFocus() { try { m_dFocusPlane = System.Convert.ToDouble(trackBarFocus.Value) / 100.0; } catch (Rx.Net.RxException xEx) { MessageBox.Show(xEx.ToString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Event handler. Called by CBCameras for selected index changed events. Selects another camera and binds it to the API. /// /// /// Source of the event. /// Event information. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void CBCameras_SelectedIndexChanged(object sender, EventArgs e) { try { StartCamera(); } catch (Rx.Net.RxException xEx) { MessageBox.Show(xEx.ToString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Starts a camera. /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void StartCamera() { try { if (m_xCamServer.GetCameraCount() > 0) { // Stop the camera and set the buttons correctly m_xCamServer.GetCamera(m_uiCamIndex).Stop(); m_xCamBuffer.Clear(); // Get the selected index m_uiCamIndex = (uint) CBCameras.SelectedIndex; // If this is a new camera there comes its first image m_bFirstImageOfCamera = true; // Load the default calibration of the camera (and load the gray image too) Rx.LFR.Net.Calibration xDefaultCalibration = new Rx.LFR.Net.Calibration(); Rx.LFR.Net.CalibrationManager.LoadDefaultCalibration(xDefaultCalibration, m_xCamServer.GetCamera(m_uiCamIndex), true); m_xCudaCompute.ApplyCalibration(xDefaultCalibration, true); // Start the camera. Depending on the given trigger mode, the camera starts to capture images or waits for a trigger m_xCamServer.GetCamera(m_uiCamIndex).Start(Rx.InteropNet.Runtime30.Camera.ETriggerMode.Camera_FreeRun); m_bCameraStopped = false; // Set the GUI controls butStartVideo.Enabled = false; butStopVideo.Enabled = true; } } catch (Rx.Net.RxException xEx) { MessageBox.Show(xEx.ToString()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Event handler. Called by butStartVideo for click events. /// /// /// Source of the event. /// Event information. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void butStartVideo_Click(object sender, EventArgs e) { // Start the camera StartCamera(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Event handler. Called by butStopVideo for click events. /// /// /// Source of the event. /// Event information. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void butStopVideo_Click(object sender, EventArgs e) { // Stop the camera m_bCameraStopped = true; m_xCamServer.GetCamera(m_uiCamIndex).Stop(); // Set the GUI controls butStartVideo.Enabled = true; butStopVideo.Enabled = false; } } }