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