Files
cms_thermo_active/ThermalImageStreamerDemo/MainForm.cs
T

794 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Flir.Atlas.Image;
using Flir.Atlas.Live.Device;
using Flir.Atlas.Live.Discovery;
using Newtonsoft.Json;
using ThermoCamUtils;
namespace ThermalImageStreamerDemo
{
public partial class MainForm : Form
{
#region Private Fields
private const string FileFilter = "IR Image Files(*.jpg;*.img;*.seq;*.fcf)|*.jpg;*.img;*.seq;*.fcf|All files (*.*)|*.*";
private readonly Timer _timerRefreshUi = new Timer();
#endregion Private Fields
#if false
private RecorderForm _recorder;
#endif
#region Protected Fields
protected const string colorPath = "images\\Color";
protected const string confFileName = "ThermoConf.json";
#if false
protected const string currImgFile = "ThermalData.jpg";
#endif
protected const string thermPath = "images\\Therm";
protected int currPoint = -1;
/// <summary>
/// Contenitore oggetti Image x FlirCam
/// </summary>
protected ImageData ImgData = new ImageData();
protected Stopwatch sw = new Stopwatch();
#endregion Protected Fields
#region Public Fields
// Config File Names
public static readonly string BASE_PATH = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
#endregion Public Fields
#region Public Constructors
public MainForm()
{
InitializeComponent();
_timerRefreshUi.Interval = 100;
_timerRefreshUi.Tick += _timerRefreshUi_Tick;
_timerRefreshUi.Start();
// collego eventi ImgData
ImgData.eh_CameraConnected += ImgData_eh_CameraConnected;
ImgData.eh_CameraDisposed += ImgData_eh_CameraDisposed;
ImgData.eh_CameraConnStatusChanged += ImgData_eh_CameraConnStatusChanged;
// cerco se ho un set di parametri già impostati...
tryReloadConf();
// sistemo le conf temp
setRangeTemp();
// calcolo i currConf.destPoints
updateDestPt();
}
#endregion Public Constructors
#region Private Properties
private bool liveView
{
get
{
return checkLive.Checked;
}
set
{
checkLive.Checked = value;
}
}
#endregion Private Properties
#region Protected Properties
protected string confPath
{
get
{
// se esiste il file... path assoluto
string answ = confFileName;
if (!Path.IsPathRooted(answ))
{
answ = BASE_PATH + "\\" + confFileName;
}
return answ;
}
}
protected ThermoCamConf currConf
{
get
{
return ImgData.currConf;
}
set
{
ImgData.currConf = value;
}
}
protected int dimX
{
get
{
int answ = 100;
int.TryParse(txtAB.Text, out answ);
currConf.TargetSize.X = answ;
return answ;
}
set
{
currConf.TargetSize.X = value;
txtAB.Text = $"{value}";
}
}
protected int dimY
{
get
{
int answ = 100;
int.TryParse(txtBC.Text, out answ);
currConf.TargetSize.Y = answ;
return answ;
}
set
{
currConf.TargetSize.Y = value;
txtBC.Text = $"{value}";
}
}
protected double maxRangeTemp
{
get
{
double answ = 1000;
double.TryParse(txtMaxScale.Text, out answ);
return answ;
}
set
{
txtMaxScale.Text = $"{value:N0}";
}
}
protected double minRangeTemp
{
get
{
double answ = 0;
double.TryParse(txtMinScale.Text, out answ);
return answ;
}
set
{
txtMinScale.Text = $"{value:N0}";
}
}
protected bool pointSetup
{
get
{
return chkPointSetup.Checked;
}
set
{
chkPointSetup.Checked = value;
}
}
protected bool readTemp
{
get
{
return chkReadTemp.Checked;
}
set
{
chkReadTemp.Checked = value;
}
}
protected bool saveEnabled
{
get
{
return chkSaveAll.Checked;
}
set
{
chkSaveAll.Checked = value;
}
}
protected bool showOrigBig
{
get
{
return chkShowOrig.Checked;
}
set
{
chkShowOrig.Checked = value;
}
}
#endregion Protected Properties
#region Private Methods
private void _recorder_SelectedFileMouseDoubleClick(object sender, SelectedFileEventArgs e)
{
var playback = new PlaybackForm(e.FilePath);
playback.Show();
}
private void _timerRefreshUi_Tick(object sender, EventArgs e)
{
// se è in live view --> continuo
if (liveView)
{
ImgData.takePicture(saveEnabled);
processImage();
refreshDisplay();
}
// avanzo prog bar
progBar.Increment(3);
if (progBar.Value >= progBar.Maximum)
{
progBar.Value = 0;
}
}
private void btnLoad_Click(object sender, EventArgs e)
{
// "" --> carica ultima scattata (altrimenti nome)
ImgData.fileLoad("");
// aggiorno visualizzazione
processImage();
refreshDisplay();
}
private void btnReset_Click(object sender, EventArgs e)
{
pointSetup = true;
currConf.OrigPoints = new SetPoints();
}
private void btnSave_Click(object sender, EventArgs e)
{
ImgData.takePicture(true);
processImage();
refreshDisplay();
}
private void checkLive_CheckedChanged(object sender, EventArgs e)
{
// cambio periodo timer!
_timerRefreshUi.Interval = checkLive.Checked ? 100 : 500;
}
private void chkPointSetup_CheckedChanged(object sender, EventArgs e)
{
// deselezione Get Temp
if (readTemp)
{
readTemp = false;
}
}
private void chkReadTemp_CheckedChanged(object sender, EventArgs e)
{
// deselezione setup punti
if (pointSetup)
{
pointSetup = false;
}
if (!readTemp)
{
lblReadTemp.Text = "? °C";
}
}
private void chkShowOrig_CheckedChanged(object sender, EventArgs e)
{
refreshDisplay();
}
private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
{
ImgData.DisconnectCamera();
}
private void discoveryToolStripMenuItem_Click(object sender, EventArgs e)
{
var discoveryDlg = new DiscoveryForm();
if (discoveryDlg.ShowDialog() == DialogResult.OK)
{
ImgData.ConnectCamera(discoveryDlg.SelectedCameraDevice);
// salvo nome camera in conf attuale!
currConf.CameraName = discoveryDlg.SelectedCameraDevice.Name;
saveConf();
}
}
private void displayImages()
{
if (ImgData.Thermal != null)
{
lblImgA.Text = showOrigBig ? "ORIGINAL image" : "FINAL image";
lblImgB.Text = showOrigBig ? "FINAL image" : "ORIGINAL image";
pBoxA.Image = showOrigBig ? ImgData.ColorTransf : ImgData.Decorated;
pBoxB.Image = showOrigBig ? ImgData.Decorated : ImgData.ColorTransf;
pBoxC.Image = ImgData.GrayTransf;
}
}
private void ImgData_eh_CameraConnected(object sender, EventArgs e)
{
#if false
_timerRefreshUi.Start();
#endif
_timerRefreshUi.Interval = 100;
}
private void ImgData_eh_CameraConnStatusChanged(object sender, Flir.Atlas.Live.ConnectionStatusChangedEventArgs e)
{
BeginInvoke((Action)(() => toolStripConnectionStatus.Text = e.Status.ToString()));
BeginInvoke((Action)(() => cameraToolStripMenuItem.Enabled = e.Status == ConnectionStatus.Connected));
// se si disconnette --> NUOVA richiesta connessione alla CHILD...
// TODO FARE!!!
}
private void ImgData_eh_CameraDisposed(object sender, EventArgs e)
{
#if false
_timerRefreshUi.Stop();
#endif
_timerRefreshUi.Interval = 500;
}
#if false
private void Camera_ConnectionStatusChanged(object sender, Flir.Atlas.Live.ConnectionStatusChangedEventArgs e)
{
BeginInvoke((Action)(() => toolStripConnectionStatus.Text = e.Status.ToString()));
BeginInvoke((Action)(() => cameraToolStripMenuItem.Enabled = e.Status == ConnectionStatus.Connected));
// se si disconnette --> NUOVA richiesta connessione alla CHILD...
// TODO FARE!!!
}
#endif
#if false
private void DisconnectCamera()
{
if (IRCam.ThermoCamera == null) return;
IRCam.ThermoCamera.Disconnect();
}
#endif
#if false
private void DisposeCamera()
{
_timerRefreshUi.Stop();
if (IRCam.ThermoCamera == null) return;
if (_recorder != null)
{
_recorder.UnInitialize();
_recorder.Dispose();
}
IRCam.ThermoCamera.ConnectionStatusChanged -= Camera_ConnectionStatusChanged;
IRCam.ThermoCamera.GetImage().Changed -= Image_Changed;
IRCam.ThermoCamera.Dispose();
}
#endif
#if false
private void Image_Changed(object sender, Flir.Atlas.Image.ImageChangedEventArgs e)
{
IsDirty = true;
}
#endif
private void lblOrigA_Click(object sender, EventArgs e)
{
lblOrigA.ForeColor = toggleEditPoint(0);
}
private void lblOrigB_Click(object sender, EventArgs e)
{
lblOrigB.ForeColor = toggleEditPoint(1);
}
private void lblOrigC_Click(object sender, EventArgs e)
{
lblOrigC.ForeColor = toggleEditPoint(2);
}
private void lblOrigD_Click(object sender, EventArgs e)
{
lblOrigD.ForeColor = toggleEditPoint(3);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
#if false
if (_recorder != null && _recorder.IsDisposed == false)
{
_recorder.Dispose();
}
#endif
ImgData.DisposeCamera();
}
private void MainForm_Load(object sender, EventArgs e)
{
}
private void MainForm_Shown(object sender, EventArgs e)
{
// avvio l'autoconnessione
if (!string.IsNullOrEmpty(currConf.CameraName))
{
discoveryCamera();
}
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
using (var dialog = new OpenFileDialog())
{
dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + @"\FLIR";
dialog.Filter = FileFilter;
if (dialog.ShowDialog() != DialogResult.OK) return;
var playback = new PlaybackForm(dialog.FileName);
playback.Show();
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
// calcolo la ratio img originale --> pictureBox
double ratio = 1;
try
{
if (ImgData.Origin != null && ImgData.Origin.Width > 0)
{
ratio = (double)pBoxA.Width / ImgData.Origin.Width;
}
}
catch
{ }
// trasformo punto in equivalente originale
var mea = (MouseEventArgs)e;
ImgData.lastPoint = new Point() { X = (int)(mea.X / ratio), Y = (int)(mea.Y / ratio) };
lblPoint.Text = $"({mea.X},{mea.Y}) --> ({ImgData.lastPoint.X},{ImgData.lastPoint.Y})";
if (pointSetup)
{
// max 4 punti... se sono già FULL --> imposto singolo valore nuovo
if (currConf.OrigPoints.curr >= 4)
{
if (currPoint >= 0)
{
currConf.OrigPoints.Coords[currPoint] = ImgData.lastPoint;
}
else
{
currConf.OrigPoints = new SetPoints();
}
}
else
{
// salvo coordinate in base al num corrente...
try
{
currConf.OrigPoints.Coords.Add(ImgData.lastPoint);
currConf.OrigPoints.curr++;
}
catch
{ }
}
// salvo conf
saveConf();
// aggiorno visualizzazione
processImage();
refreshDisplay();
}
else if (readTemp)
{
// x ora fisso 1 solo valore...
ImgData.saveMeasurePoint(false);
// aggiorno visualizzazione
processImage();
refreshDisplay();
}
}
private void processImage()
{
// disegno immagine
ImgData.getTemperatures(readTemp);
ImgData.calculateTarget();
}
private void recorderToolStripMenuItem_Click(object sender, EventArgs e)
{
#if false
if (_recorder == null || _recorder.IsDisposed)
{
_recorder = new RecorderForm();
_recorder.Initialize(IRCam.ThermoCamera);
_recorder.SelectedFileMouseDoubleClick += _recorder_SelectedFileMouseDoubleClick;
}
_recorder.Show();
_recorder.Focus();
#endif
}
private void refreshDisplay()
{
ImgData.drawCrossAtPoints();
displayImages();
updateDisplay();
updateTempDisplay();
updateStatDisplay();
}
/// <summary>
/// Salva su file il file di conf corrente
/// </summary>
/// <returns></returns>
private bool saveConf()
{
bool answ = false;
try
{
string rawData = JsonConvert.SerializeObject(currConf, Formatting.Indented);
File.WriteAllText(confPath, rawData);
answ = true;
}
catch
{ }
return answ;
}
/// <summary>
/// Sistema le temp range min/Max
/// </summary>
private void setRangeTemp()
{
currConf.TargetRange.Min = minRangeTemp;
currConf.TargetRange.Max = maxRangeTemp;
}
#if false
/// <summary>
/// recupera immagine effettuando eventuale salvataggio
/// </summary>
/// <param name="doSave"></param>
private void takePicture(bool doSave)
{
sw.Restart();
if (!IsDirty) return;
IsDirty = false;
if (IRCam.ThermoCamera == null) return;
IRCam.ThermoCamera.GetImage().EnterLock();
try
{
ImgData.Thermal = (ThermalImage)IRCam.ThermoCamera.GetImage();
ImgData.Thermal.TemperatureUnit = TemperatureUnit.Celsius;
ImgData.Thermal.Scale.IsAutoAdjustEnabled = true;
ImgData.lastTempRange = new Range<double>(ImgData.Thermal.Scale.Range.Minimum, ImgData.Thermal.Scale.Range.Maximum);
// salvo img locale
ImgData.Origin = ImgData.Thermal.Image;
ImgData.Decorated = ImgData.Thermal.Image;
// recupero le temperature...
ImgData.readAllTemperatures();
//verifico se devo salvare...
if (doSave)
{
ImgData.fileSave();
}
}
catch (Exception exception)
{
Trace.TraceError(exception.Message);
}
finally
{
IRCam.ThermoCamera.GetImage().ExitLock();
}
sw.Stop();
msLastCam = sw.ElapsedMilliseconds;
}
#endif
/// <summary>
/// Verifica se il punto era in edit, altrimenti segnala e lo attiva... restituendo colore x il controllo
/// </summary>
/// <param name="selPoint"></param>
private Color toggleEditPoint(int selPoint)
{
Color answ = Color.Black;
lblOrigA.ForeColor = answ;
lblOrigB.ForeColor = answ;
lblOrigC.ForeColor = answ;
lblOrigD.ForeColor = answ;
readTemp = false;
pointSetup = true;
if (currPoint == selPoint)
{
// deseleziono
currPoint = -1;
}
else
{
// indico selezionato
currPoint = selPoint;
answ = Color.Green;
}
return answ;
}
private void tryReloadConf()
{
if (File.Exists(confPath))
{
// se non è vuoto....
string rawData = File.ReadAllText(confPath);
if (!string.IsNullOrEmpty(rawData))
{
try
{
currConf = JsonConvert.DeserializeObject<ThermoCamConf>(rawData);
}
catch (Exception exc)
{ }
}
}
}
private void txtAB_TextChanged(object sender, EventArgs e)
{
// ricalcolo in proporzione altro valore...
dimY = (int)((double)dimX * 256 / 320);
// aggiorno punti dest
updateDestPt();
}
private void txtBC_TextChanged(object sender, EventArgs e)
{
// ricalcolo in proporzione altro valore...
dimX = (int)((double)dimY * 320 / 256);
// aggiorno punti dest
updateDestPt();
}
private void txtMaxScale_TextChanged(object sender, EventArgs e)
{
setRangeTemp();
}
private void txtMinScale_TextChanged(object sender, EventArgs e)
{
setRangeTemp();
}
private void updateDestPt()
{
currConf.DestPoints.Coords = new List<Point>();
// ciclo i punti A-B-C-D...
currConf.DestPoints.Coords.Add(new Point() { X = 0, Y = 0 });
currConf.DestPoints.Coords.Add(new Point() { X = dimX, Y = 0 });
currConf.DestPoints.Coords.Add(new Point() { X = dimX, Y = dimY });
currConf.DestPoints.Coords.Add(new Point() { X = 0, Y = dimY });
// salvo conf
saveConf();
}
private void updateDisplay()
{
lblOrigA.Text = "A";
lblOrigB.Text = "B";
lblOrigC.Text = "C";
lblOrigD.Text = "D";
// popolo
if (currConf.OrigPoints.Coords.Count > 0)
{
lblOrigA.Text = $"A: ({currConf.OrigPoints.Coords[0].X},{currConf.OrigPoints.Coords[0].Y})";
}
if (currConf.OrigPoints.Coords.Count > 1)
{
lblOrigB.Text = $"B: ({currConf.OrigPoints.Coords[1].X},{currConf.OrigPoints.Coords[1].Y})";
}
if (currConf.OrigPoints.Coords.Count > 2)
{
lblOrigC.Text = $"C: ({currConf.OrigPoints.Coords[2].X},{currConf.OrigPoints.Coords[2].Y})";
}
if (currConf.OrigPoints.Coords.Count > 3)
{
lblOrigD.Text = $"D: ({currConf.OrigPoints.Coords[3].X},{currConf.OrigPoints.Coords[3].Y})";
ImgData.calculateTarget();
}
}
private void updateStatDisplay()
{
if (ImgData.ExTime.Stats.Count > 0)
{
try
{
lblStats.Text = $"Camera: {ImgData.lastStatTime("ImageAcquisition")}ms | Persp {ImgData.lastStatTime("ImageTransf")}ms | Color {ImgData.lastStatTime("ImageColor")}ms | Points {ImgData.lastStatTime("AddPoints")}ms | Measures {ImgData.lastStatTime("GetAllTemperatures")}ms";
}
catch
{ }
}
}
private void updateTempDisplay()
{
if (ImgData.Thermal != null)
{
if (readTemp)
{
// mostro temp da FLIR
lblReadTemp.Text = $"{ImgData.lastReadTemp:N2} °C";
try
{
// mostro minimo / massimo
lblMinTemp.Text = $"{ImgData.lastTempRange.Minimum:N2}";
lblMaxTemp.Text = $"{ImgData.lastTempRange.Maximum:N2}";
}
catch
{ }
}
}
}
#endregion Private Methods
#region Public Methods
public void discoveryCamera()
{
var discoveryDialog = new DiscoveryForm();
discoveryDialog.CameraName = currConf.CameraName;
if (!string.IsNullOrEmpty(currConf.CameraName))
{
//discoveryDialog.WindowState = FormWindowState.Minimized;
if (discoveryDialog.ShowDialog() == DialogResult.OK)
{
ImgData.ConnectCamera(discoveryDialog.SelectedCameraDevice);
}
}
}
#endregion Public Methods
}
}