322 lines
11 KiB
C#
322 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Windows;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Threading;
|
|
|
|
namespace EloThermal_windows
|
|
{
|
|
/// <summary>
|
|
/// MainWindow.xaml 的交互逻辑
|
|
/// </summary>
|
|
public partial class SmartWindow : Window
|
|
{
|
|
public static SynchronizationContext s_SC = SynchronizationContext.Current;
|
|
|
|
WriteableBitmap uvcWriteableBitmap = null;
|
|
CameraSDK.INewUVCFrame uvcCallback = null;
|
|
IntPtr uvcBitmapBufferPtr;
|
|
|
|
WriteableBitmap irWriteableBitmap = null;
|
|
ThermalSDK.INewIRFrame irCallback = null;
|
|
IntPtr irBitmapBufferPtr;
|
|
ThermalSDK.INewDistance distCallback = null;
|
|
|
|
private int VIEW_WIDTH = 0;
|
|
private int VIEW_HEIGHT = 0;
|
|
private bool isUnitUS = false;
|
|
private bool isFullScreen = false;
|
|
|
|
volatile int lastIRTime = -1;
|
|
volatile float lastDistance = -1;
|
|
volatile float lastValidDistance = -1;
|
|
volatile int lastValidDistanceTime = -1;
|
|
|
|
public SmartWindow()
|
|
{
|
|
InitializeComponent();
|
|
|
|
bool ret = FaceTrackingSDK.LoadCasscade("uvc_mask_haar.xml");
|
|
Console.WriteLine("Load:" + ret);
|
|
}
|
|
|
|
|
|
private void Window_Closed(object sender, EventArgs e)
|
|
{
|
|
closeIR();
|
|
closeCamera();
|
|
}
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
if (isFullScreen)
|
|
{
|
|
this.WindowState = System.Windows.WindowState.Normal;
|
|
this.WindowStyle = System.Windows.WindowStyle.None;
|
|
this.ResizeMode = System.Windows.ResizeMode.NoResize;
|
|
this.Topmost = true;
|
|
|
|
this.Left = 0.0;
|
|
this.Top = 0.0;
|
|
this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
|
|
this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
|
|
}
|
|
}
|
|
|
|
private void Window_Initialized(object sender, EventArgs e)
|
|
{
|
|
VIEW_HEIGHT = (int)((this.Height - ControlPanel.Height.Value) / 2);
|
|
VIEW_WIDTH = (int)this.Width;
|
|
|
|
int x = EloUVCCameraConverter.getDefaultX();
|
|
int y = EloUVCCameraConverter.getDefaultY();
|
|
EloUVCCameraConverter.setOffset(x, y);
|
|
|
|
initCamera();
|
|
initIR();
|
|
|
|
openCamera();
|
|
openIR();
|
|
|
|
|
|
if (isUnitUS)
|
|
{
|
|
ThermalSDK.SetUnitMode(ThermalSDK.Thermal_Unit_US);
|
|
ThermalSDK.SetTempBoundary(30 * 1.8 + 32, 44 * 1.8 + 32, 37 * 1.8 + 32);
|
|
}
|
|
else
|
|
{
|
|
ThermalSDK.SetUnitMode(ThermalSDK.Thermal_Unit_Metric);
|
|
ThermalSDK.SetTempBoundary(30, 44, 37);
|
|
}
|
|
}
|
|
|
|
|
|
volatile List<RectF> lastValidFaces = null;
|
|
volatile int lastValidUVCTime = -1;
|
|
volatile int nextRotateTime = -1;
|
|
public void onUVCCameraCallback(IntPtr ptr, int imageWidth, int imageHeight, int channel)
|
|
{
|
|
if (channel != 3)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int curTime = System.Environment.TickCount;
|
|
|
|
Bitmap bmp = ImageHelper.ToColorBitmap(ptr, imageWidth, imageHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
Bitmap trackBmp = EloUVCCameraConverter.UVCBitmapWithIRWidth(bmp);
|
|
Bitmap convBmp = EloUVCCameraConverter.UVCBitmapWithIRSize(bmp);
|
|
bmp.Dispose();
|
|
ViewDrawer.DrawImage(this, convBmp, uvcWriteableBitmap, uvcBitmapBufferPtr, VIEW_WIDTH, VIEW_HEIGHT);
|
|
|
|
try
|
|
{
|
|
int trackWidth = trackBmp.Width;
|
|
int trackHeight = trackBmp.Height;
|
|
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, trackWidth, trackHeight);
|
|
BitmapData bitmapData = trackBmp.LockBits(rect, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
IntPtr ptrDest = bitmapData.Scan0;
|
|
|
|
List<RectI> faces = FaceTrackingSDK.DetectFaces(ptrDest, trackWidth, trackHeight, channel,
|
|
0.1f, 1.0f);
|
|
List<RectF> rectfs = EloUVCCameraConverter.OpenCVRect2Local(faces);
|
|
|
|
if ((rectfs != null) && (rectfs.Count > 0))
|
|
{
|
|
lastValidFaces = rectfs;
|
|
lastValidUVCTime = curTime;
|
|
|
|
if (curTime > nextRotateTime)
|
|
{
|
|
double sumCenterY = 0;
|
|
for (int i = 0; i < rectfs.Count; ++i)
|
|
{
|
|
sumCenterY += lastValidFaces[i].CenterY();
|
|
}
|
|
double centerY = sumCenterY / rectfs.Count;
|
|
int step = (int)((centerY - 0.5) * -0.10 * EloUVCCameraConverter.IR_HEIGHT);
|
|
|
|
if (step != 0)
|
|
{
|
|
if (centerY > 0.6)
|
|
{
|
|
ThermalSDK.Rotate(step);
|
|
}
|
|
else if (centerY < 0.4)
|
|
{
|
|
ThermalSDK.Rotate(step);
|
|
}
|
|
nextRotateTime = curTime + Math.Abs(step) * 10 + 80;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (curTime - lastValidUVCTime >= 1000)
|
|
{
|
|
lastValidFaces = null;
|
|
}
|
|
|
|
trackBmp.UnlockBits(bitmapData);
|
|
trackBmp.Dispose();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex);
|
|
}
|
|
|
|
}
|
|
public void onDistanceCallback(float distance)
|
|
{
|
|
if (distance > 0)
|
|
{
|
|
lastValidDistanceTime = System.Environment.TickCount;
|
|
lastValidDistance = distance;
|
|
}
|
|
lastDistance = distance;
|
|
}
|
|
public void onIRCameraCallback(IntPtr ptr, int width, int height, int channel)
|
|
{
|
|
if (channel != 3)
|
|
{
|
|
return;
|
|
}
|
|
Bitmap bmp = ImageHelper.ToColorBitmap(ptr, width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
ViewDrawer.DrawImage(this, bmp, irWriteableBitmap, irBitmapBufferPtr, VIEW_WIDTH, VIEW_HEIGHT);
|
|
|
|
int curTime = System.Environment.TickCount;
|
|
|
|
//Update every 500ms
|
|
if (curTime - lastIRTime >= 500)
|
|
{
|
|
if ((lastValidFaces != null) && (lastValidFaces.Count > 0))
|
|
{
|
|
int countAbnormal = 0;
|
|
int countNormal = 0;
|
|
|
|
List<TemperatureResult> results = new List<TemperatureResult>();
|
|
for (int i = 0; i < lastValidFaces.Count; ++i)
|
|
{
|
|
RectF faceF = lastValidFaces[i];
|
|
RectI face = new RectI(
|
|
(int)(faceF.X * EloUVCCameraConverter.IR_WIDTH),
|
|
(int)(faceF.Y * EloUVCCameraConverter.IR_HEIGHT),
|
|
(int)(faceF.Width * EloUVCCameraConverter.IR_WIDTH),
|
|
(int)(faceF.Height * EloUVCCameraConverter.IR_HEIGHT));
|
|
TemperatureResult temperatureResult = ThermalSDK.ReadTemperatureInRect(face);
|
|
if (temperatureResult.Judgement == ThermalSDK.Thermal_Judgement_Fever)
|
|
{
|
|
countAbnormal++;
|
|
}
|
|
else if (temperatureResult.Judgement == ThermalSDK.Thermal_Judgement_Normal)
|
|
{
|
|
countNormal++;
|
|
}
|
|
results.Add(temperatureResult);
|
|
}
|
|
|
|
|
|
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
canvasRGB.DrawWithFace(lastValidFaces, results);
|
|
canvasIR.DrawWithFace(lastValidFaces, results);
|
|
}));
|
|
|
|
|
|
if (countAbnormal > 0)
|
|
{
|
|
OnAbnormal();
|
|
}
|
|
else if (countNormal > 0)
|
|
{
|
|
OnNormal();
|
|
}
|
|
else
|
|
{
|
|
OnNobody();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
canvasRGB.DrawWithFace(null, null);
|
|
canvasIR.DrawWithFace(null, null);
|
|
}));
|
|
|
|
OnNobody();
|
|
}
|
|
lastIRTime = curTime;
|
|
}
|
|
}
|
|
|
|
private void initIR()
|
|
{
|
|
irWriteableBitmap = new WriteableBitmap(VIEW_WIDTH, VIEW_HEIGHT, 96, 96, PixelFormats.Bgr24, null);
|
|
imgIR.Source = irWriteableBitmap;
|
|
irBitmapBufferPtr = irWriteableBitmap.BackBuffer;
|
|
}
|
|
private void openIR()
|
|
{
|
|
ThermalSDK.Start();
|
|
irCallback = new ThermalSDK.INewIRFrame(onIRCameraCallback);
|
|
distCallback = new ThermalSDK.INewDistance(onDistanceCallback);
|
|
ThermalSDK.SetNewIRFrameDelegate(irCallback);
|
|
ThermalSDK.SetNewDistanceDelegate(distCallback);
|
|
}
|
|
private void closeIR()
|
|
{
|
|
ThermalSDK.SetNewIRFrameDelegate(null);
|
|
ThermalSDK.SetNewDistanceDelegate(null);
|
|
ThermalSDK.Stop();
|
|
|
|
}
|
|
private void initCamera()
|
|
{
|
|
uvcWriteableBitmap = new WriteableBitmap(VIEW_WIDTH, VIEW_HEIGHT, 96, 96, PixelFormats.Bgr24, null);
|
|
imgRGB.Source = uvcWriteableBitmap;
|
|
uvcBitmapBufferPtr = uvcWriteableBitmap.BackBuffer;
|
|
}
|
|
private void openCamera()
|
|
{
|
|
CameraSDK.OpenCamera(0, 640, 480);
|
|
uvcCallback = new CameraSDK.INewUVCFrame(onUVCCameraCallback);
|
|
CameraSDK.SetNewUVCFrame(uvcCallback);
|
|
}
|
|
private void closeCamera()
|
|
{
|
|
CameraSDK.SetNewUVCFrame(null);
|
|
CameraSDK.CloseCamera();
|
|
}
|
|
|
|
protected void OnNormal()
|
|
{
|
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
imgNormal.Visibility = Visibility.Visible;
|
|
imgAbnormal.Visibility = Visibility.Hidden;
|
|
}));
|
|
}
|
|
protected void OnAbnormal()
|
|
{
|
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
imgNormal.Visibility = Visibility.Hidden;
|
|
imgAbnormal.Visibility = Visibility.Visible;
|
|
}));
|
|
}
|
|
protected void OnNobody()
|
|
{
|
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
imgNormal.Visibility = Visibility.Hidden;
|
|
imgAbnormal.Visibility = Visibility.Hidden;
|
|
}));
|
|
}
|
|
}
|
|
}
|