过去几天我一直在使用FLIR Thermovision相机,并将一个非常简单的应用程序整合在一起,该应用程序在许多不同的地方都有一些方面(其中大部分都在stackoverflow上)。
主题
Float[,]
数组到BitmapImage
MemoryStream
和BitmapImage
1。 Active X控件
Flir Thermovision SDK 2.6附带一个ActiveX组件DLL。 AxCAMCTRLLib.dll。在WinForms应用程序中,您只需将工具添加到工具框中,然后单击并将组件拖到窗体上即可。这将自动添加对项目的正确引用。要在wpf应用程序中使用它,这将不起作用。在后面看来这似乎很容易,但它没有在他们的文档中列出。
首先,我必须手动导航到AxCAMCTRLLib.dll并将其添加到引用中。然后为项目添加一个新窗口。这将是一个隐藏窗口,仅用于托管activeX组件。这还需要WindowsFormsIntegration引用软件ActiveX组件。
using CAMCTRLLib;
using AxCAMCTRLLib;
namespace camView
{
public partial class CameraCtrl : Window
{
public AxCAMCTRLLib.AxLVCam camera;
private System.Windows.Forms.Integration.WindowsFormsHost host;
public CameraCtrl()
{
InitializeComponent();
host = new System.Windows.Forms.Integration.WindowsFormsHost();
camera = new AxCAMCTRLLib.AxLVCam();
host.Child = camera;
this.grid1.Children.Add(host);
}
}
}
现在在MainWindow我可以创建,显示然后立即隐藏一个新窗口CameraCtrl
并可以访问公共ActiveX控件。
public MainWindow()
{
InitializeComponent();
camCtrl = new CameraCtrl();
camCtrl.BeginInit();
camCtrl.Show();
camCtrl.Hide();
camCtrl.ShowInTaskbar = false;
camCtrl.ShowActivated = false;
}
必须修改OnClosing
中的 MainWindow
方法以关闭隐藏窗口。
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
camCtrl.Close();
base.OnClosing(e);
}
有了这个,我现在可以访问activex对象中包含的所有控制方法。
2。将[,]数组浮动到BitmapImage
来自相机的输出图像可以以多种不同的格式返回,但对于我正在使用的特定相机,它会返回包含object
的{{1}}。由于它是热的,输出像素值代表温度。这意味着必须将它们标准化,然后先转换为float[,]
,然后存储在Bitmap
中,然后添加到MemoryStream
的来源。我使用的方法如下。
BitmapImage
3。显示图像
我创建了一个简单的帮助类:
private BitmapImage setDisplayImage(float[,] image)
{
float[,] tempStoreImage = new float[240 , 320];
float max = -10000.0f, min = 10000.0f;
BitmapImage localBitmap;
for (int j = 0; j < 320; j++)
{
for (int i = 0; i < 240; i++)
{
tempStoreImage[i,j] = image[j,i];//have to transpose the image from cam
if (tempStoreImage[i,j] > max)
{
max = tempStoreImage[i,j];
}
if (tempStoreImage[i,j] < min)
{
min = tempStoreImage[i,j];
}
}
}
if(max != min)//can't divide by zero
{
System.Drawing.Bitmap newBitmap = new System.Drawing.Bitmap(320, 240);
for (int i = 0; i < 240; i++)
{
for (int j = 0; j < 320; j++)
{
tempStoreImage[i,j] = (float)Math.Round((double)(tempStoreImage[i,j] - min) * 255 / (max - min));//Normalize and set between 0 - 255
System.Drawing.Color newColor = System.Drawing.Color.FromArgb((int)tempStoreImage[i, j],0, 0, 0);//Gray scale color using alpha channel
newBitmap.SetPixel(j, i, newColor);
}
}
System.Drawing.Image img = (System.Drawing.Image)newBitmap;
MemoryStream stream = new MemoryStream();
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);//add Bitmap to memory stream
stream.Position = 0;
localBitmap = new BitmapImage();
localBitmap.BeginInit();
localBitmap.StreamSource = stream; //
localBitmap.EndInit();
}
else localBitmap = new BitmapImage();//dark image
return localBitmap;
}
然后在MainWindow中创建了一个静态助手类对象(可能不需要是静态的,但我打算在其他类中使用它。) class BindData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
BitmapImage _image;
public BitmapImage Image
{
get { return _image; }
set
{
_image = value;
_image.Freeze();
OnPropertyChanged("Image");
}
}
}
并设置BindData bind = new BindData()
。然后设置绑定和窗口大小以匹配我的数组:
image1.DataContext = bind
最后使用<Image Height="240" HorizontalAlignment="Left" Margin="204,21,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="320" Source="{Binding Image}"/>
System.Timers.Timer
private void kill_Click(object sender,RoutedEventArgs e) { continueDisplay = false; }
我使用计时器遇到了一些事情。首先,应用程序时间和摄像机时间不一样,所以我在捕获开始时停止计时器并在结束后重新启动计时器。幸运的是,线程等待相机返回图像。这在很大程度上解决了滞后问题。其次,private void cameraCap()
{
if (continueDisplay)
{
captureTimer.Stop();
lock (camCtrl)
{
object yo = camCtrl.camera.GetImage(3);
bind.Image = setDisplayImage(yo as float[,]);
}
captureTimer.Start();
}
else
captureTimer.Stop();
}
private void capture_Click(object sender, RoutedEventArgs e)
{
continueDisplay = true;
captureTimer.Start();
}
声明至关重要。没有它,您将获得“必须在与DependencyObject相同的线程上创建DependencySource”。错误一旦启动。 Freeze方法使图像可供其他线程使用。
答案 0 :(得分:0)
这确实属于codereview.stackexchange.com