739 lines
26 KiB
C#
739 lines
26 KiB
C#
using System.Data;
|
||
using System.Diagnostics;
|
||
using System.Drawing.Imaging;
|
||
using AntdUI;
|
||
using DH.Commons.Base;
|
||
using DH.Commons.Enums;
|
||
using DH.Commons.Helper;
|
||
using DH.Commons.Models;
|
||
using DH.Devices.Camera;
|
||
using HalconDotNet;
|
||
using OpenCvSharp.Extensions;
|
||
|
||
|
||
namespace DHSoftware.Views
|
||
{
|
||
public partial class VisualLocalizationWindow : Window
|
||
{
|
||
//采集状态
|
||
private volatile bool isCapturing=false;
|
||
//定位状态
|
||
private volatile bool isLocationing = false;
|
||
//算法
|
||
HDevEngine MyEngine = new HDevEngine();
|
||
HDevProcedure Procedure;
|
||
HDevProcedureCall ProcCall;
|
||
//背景图
|
||
HImage backImage = new HImage();
|
||
//当前相机
|
||
Do3ThinkCamera Do3ThinkCamera = new Do3ThinkCamera();
|
||
//定时器
|
||
private System.Threading.Timer Timer;
|
||
|
||
List<VisualLocalization> localizations = new List<VisualLocalization>();
|
||
|
||
|
||
public VisualLocalizationWindow()
|
||
{
|
||
InitializeComponent();
|
||
Load += VisualLocalizationWindow_Load;
|
||
btnSelectModel.Click += BtnSelectModel_Click;
|
||
btnSelectBackImg.Click += BtnSelectBackImg_Click;
|
||
btnAcquisition.Click += BtnAcquisition_Click;
|
||
btnLocalization.Click += BtnLocalization_Click;
|
||
btnForward.MouseDown += BtnForward_MouseDown;
|
||
btnForward.MouseUp += BtnForward_MouseUp;
|
||
btnReverse.MouseDown += BtnReverse_MouseDown;
|
||
btnReverse.MouseUp += BtnReverse_MouseUp;
|
||
btnSaveImg.Click += BtnSaveImg_Click;
|
||
btnSavePos.Click += BtnSavePos_Click;
|
||
sltCameraName.SelectedIndexChanged += SltCameraName_SelectedIndexChanged;
|
||
btnMotorForward.MouseDown += BtnMotorForward_MouseDown;
|
||
btnMotorForward.MouseUp += MotorButton_MouseUp;
|
||
btnMotorReverse.MouseDown += BtnMotorReverse_MouseDown;
|
||
btnMotorReverse.MouseUp += MotorButton_MouseUp;
|
||
btnMotorZero.Click += BtnMotorZero_Click;
|
||
btnSaveMotorPos.Click += BtnSaveMotorPos_Click;
|
||
panelMotor.Visible = false;
|
||
|
||
|
||
}
|
||
|
||
private void BtnSaveMotorPos_Click(object? sender, EventArgs e)
|
||
{
|
||
//根据工位查找点位
|
||
PLCItem? pLCItem = ConfigModel.PLCBaseList?
|
||
.FirstOrDefault()?
|
||
.PLCItemList?
|
||
.Where(it => it.Name == "相机步进位置").FirstOrDefault();
|
||
if (pLCItem == null)
|
||
{
|
||
AntdUI.Message.warn(this, $"未找到相机步进位置地址,请检查该地址是否存在于点位表!", autoClose: 3);
|
||
return;
|
||
}
|
||
|
||
PLCItem? pLCItem1 = ConfigModel.GlobalList?
|
||
.FirstOrDefault()?
|
||
.StartProcessList?
|
||
.Where(it => it.Name == "相机步进位置").FirstOrDefault();
|
||
|
||
if (pLCItem1 == null)
|
||
{
|
||
pLCItem1 = new PLCItem();
|
||
pLCItem1.Name = pLCItem.Name;
|
||
pLCItem1.Address = pLCItem.Address;
|
||
pLCItem1.Value = iptMotorPos.Text;
|
||
pLCItem1.Type = pLCItem.Type;
|
||
pLCItem1.StartExecute = true;
|
||
ConfigModel.GlobalList?
|
||
.FirstOrDefault()?
|
||
.StartProcessList?.Add(pLCItem1);
|
||
}
|
||
else
|
||
{
|
||
pLCItem1.Value = iptMotorPos.Text;
|
||
}
|
||
|
||
ConfigHelper.SaveConfig();
|
||
AntdUI.Message.success(this, "保存成功!", autoClose: 3);
|
||
}
|
||
private CancellationTokenSource? _motorCts;
|
||
private bool _isMotorOperating;
|
||
private bool _isHoming;
|
||
|
||
|
||
|
||
private CancellationTokenSource _cts;
|
||
private bool _isBusy;
|
||
|
||
// 电机正转控制
|
||
private async void BtnMotorForward_MouseDown(object sender, MouseEventArgs e)
|
||
{
|
||
if (_isBusy) return;
|
||
_isBusy = true;
|
||
|
||
try
|
||
{
|
||
// 获取并处理速度值
|
||
if (!int.TryParse(iptMotorSpeed.Text, out int speed) || speed == 0)
|
||
{
|
||
AntdUI.Message.warn(this, "速度值无效");
|
||
return;
|
||
}
|
||
int actualSpeed = Math.Abs(speed); // 正转取绝对值
|
||
|
||
// 启动PLC控制
|
||
_cts?.Dispose();
|
||
_cts = new CancellationTokenSource();
|
||
MainWindow.Instance.PLC.MotorSpeed(actualSpeed);
|
||
MainWindow.Instance.PLC.MotorTest(true);
|
||
|
||
// 实时更新循环
|
||
while (!_cts.IsCancellationRequested)
|
||
{
|
||
var pos = await Task.Run(() => MainWindow.Instance.PLC.ReadMotorRealPos());
|
||
iptMotorPos.Text = pos.ToString();
|
||
await Task.Delay(50);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
AntdUI.Message.error(this, $"正转异常: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
MainWindow.Instance.PLC.MotorTest(false);
|
||
_isBusy = false;
|
||
}
|
||
}
|
||
|
||
// 电机反转控制
|
||
// 电机反转控制(带原点保护)
|
||
private async void BtnMotorReverse_MouseDown(object sender, MouseEventArgs e)
|
||
{
|
||
if (_isBusy) return;
|
||
_isBusy = true;
|
||
|
||
try
|
||
{
|
||
// 获取并处理速度值
|
||
if (!int.TryParse(iptMotorSpeed.Text, out int speed) || speed == 0)
|
||
{
|
||
AntdUI.Message.warn(this, "速度值无效");
|
||
return;
|
||
}
|
||
int actualSpeed = -Math.Abs(speed);
|
||
|
||
// 实时位置检查(启动前)
|
||
int currentPos = MainWindow.Instance.PLC.ReadMotorRealPos();
|
||
if (currentPos <= 0)
|
||
{
|
||
AntdUI.Message.info(this, "已在原点位置");
|
||
return;
|
||
}
|
||
|
||
// 启动PLC控制
|
||
_cts?.Dispose();
|
||
_cts = new CancellationTokenSource();
|
||
MainWindow.Instance.PLC.MotorSpeed(actualSpeed);
|
||
MainWindow.Instance.PLC.MotorTest(true);
|
||
|
||
// 带保护的实时更新循环
|
||
while (!_cts.IsCancellationRequested)
|
||
{
|
||
currentPos = await Task.Run(() => MainWindow.Instance.PLC.ReadMotorRealPos());
|
||
|
||
// 位置边界保护
|
||
if (currentPos <= 0)
|
||
{
|
||
_cts.Cancel();
|
||
|
||
break;
|
||
}
|
||
|
||
// 更新UI
|
||
this.Invoke((MethodInvoker)delegate {
|
||
iptMotorPos.Text = currentPos.ToString();
|
||
});
|
||
|
||
await Task.Delay(50);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
AntdUI.Message.error(this, $"反转异常: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
MainWindow.Instance.PLC.MotorTest(false);
|
||
_isBusy = false;
|
||
}
|
||
}
|
||
|
||
// 停止控制(正反转共用)
|
||
private void MotorButton_MouseUp(object sender, MouseEventArgs e) {
|
||
_cts?.Cancel();
|
||
iptMotorPos.Text = MainWindow.Instance.PLC.ReadMotorRealPos().ToString();
|
||
}
|
||
|
||
// 回零操作
|
||
private async void BtnMotorZero_Click(object sender, EventArgs e)
|
||
{
|
||
if (_isBusy) return;
|
||
_isBusy = true;
|
||
btnMotorForward.Enabled = btnMotorReverse.Enabled = false;
|
||
|
||
try
|
||
{
|
||
// 获取速度值
|
||
if (!int.TryParse(iptMotorSpeed.Text, out int speed) || speed <= 0)
|
||
{
|
||
AntdUI.Message.warn(this, "速度值无效");
|
||
return;
|
||
}
|
||
|
||
// 执行回零
|
||
MainWindow.Instance.PLC.MotorSpeed(speed);
|
||
await Task.Run(() => MainWindow.Instance.PLC.MotorToZero(true));
|
||
|
||
// 等待回零完成
|
||
while (MainWindow.Instance.PLC.ReadMotorRealPos() != 0)
|
||
{
|
||
iptMotorPos.Text = MainWindow.Instance.PLC.ReadMotorRealPos().ToString();
|
||
await Task.Delay(100);
|
||
}
|
||
|
||
await Task.Run(() => MainWindow.Instance.PLC.MotorToZero(false));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
AntdUI.Message.error(this, $"回零失败: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
btnMotorForward.Enabled = btnMotorReverse.Enabled = true;
|
||
_isBusy = false;
|
||
iptMotorPos.Text = MainWindow.Instance.PLC.ReadMotorRealPos().ToString();
|
||
}
|
||
}
|
||
|
||
private void SltCameraName_SelectedIndexChanged(object sender, IntEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
localizations = VisualLocalization.LoadAll();
|
||
|
||
}
|
||
catch
|
||
{
|
||
|
||
}
|
||
string cameraName= sltCameraName.Text;
|
||
Do3ThinkCamera = MainWindow.Instance.Cameras.Where(it => it.CameraName == cameraName).FirstOrDefault() ?? new Do3ThinkCamera();
|
||
VisualLocalization? visual= localizations.Where(it=>it.CameraName==cameraName).FirstOrDefault();
|
||
if (visual != null)
|
||
{
|
||
iptModel.Text = visual.ModelPath;
|
||
iptBackImg.Text = visual.ImgPath;
|
||
iptThreshold.Text = visual.Threshold;
|
||
sltDirection.SelectedIndex = visual.Direction == "正方向" ? 0 : 1;
|
||
iptSpeed.Text = visual.Speed;
|
||
}
|
||
if (Do3ThinkCamera.IsZoomCamera)
|
||
{
|
||
panelMotor.Visible=true;
|
||
}
|
||
else
|
||
{
|
||
panelMotor.Visible = false;
|
||
}
|
||
}
|
||
|
||
private void BtnSavePos_Click(object? sender, EventArgs e)
|
||
{
|
||
var form = new SavePositionControl(this,Convert.ToInt32(iptPosition.Text)) { Size = new Size(300, 300) };
|
||
AntdUI.Modal.open(new AntdUI.Modal.Config(this, "", form, TType.None)
|
||
{
|
||
BtnHeight = 0,
|
||
});
|
||
if (form.submit)
|
||
{
|
||
VisualLocalization visualLocalization = new VisualLocalization();
|
||
//保存用户操作到文件
|
||
visualLocalization.CameraName = sltCameraName.Text;
|
||
visualLocalization.ModelPath=iptModel.Text;
|
||
visualLocalization.ImgPath=iptBackImg.Text;
|
||
visualLocalization.Threshold=iptThreshold.Text;
|
||
visualLocalization.Direction=sltDirection.Text;
|
||
visualLocalization.Speed=iptSpeed.Text;
|
||
visualLocalization.Save();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存图像
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnSaveImg_Click(object? sender, EventArgs e)
|
||
{
|
||
if (!isCapturing)
|
||
{
|
||
AntdUI.Message.warn(this, $"未开始采集,无法保存图像!", autoClose: 3);
|
||
return;
|
||
}
|
||
Bitmap bitmap =imageViewerControl1.GetCurrentSnapshot();
|
||
using (SaveFileDialog saveDialog = new SaveFileDialog())
|
||
{
|
||
saveDialog.Title = "保存图像文件";
|
||
saveDialog.Filter = "JPEG 图像|*.jpg";
|
||
saveDialog.FilterIndex = 0;
|
||
saveDialog.AddExtension = true;
|
||
saveDialog.OverwritePrompt = true;
|
||
|
||
if (saveDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
bitmap.Save(saveDialog.FileName, ImageFormat.Jpeg);
|
||
AntdUI.Message.success(this, $"图像保存成功!", autoClose: 3);
|
||
}
|
||
else
|
||
{
|
||
AntdUI.Message.warn(this, $"取消图像保存操作!", autoClose: 3);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 定位
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnLocalization_Click(object? sender, EventArgs e)
|
||
{
|
||
if (!isCapturing)
|
||
{
|
||
AntdUI.Message.warn(this, $"未开始采集,无法开始定位!", autoClose: 3);
|
||
return;
|
||
}
|
||
if (!isLocationing)
|
||
{
|
||
bool direction =sltDirection.SelectedIndex==0?true:false;
|
||
if (string.IsNullOrEmpty(iptSpeed.Text))
|
||
{
|
||
AntdUI.Message.warn(this, $"请输入速度!", autoClose: 3);
|
||
return;
|
||
}
|
||
int speed = 0;
|
||
|
||
try
|
||
{
|
||
bool isValid = int.TryParse(iptSpeed.Text, out speed);
|
||
if (!isValid)
|
||
{
|
||
AntdUI.Message.warn(this, $"输入的速度不是有效值!", autoClose: 3);
|
||
return;
|
||
}
|
||
}
|
||
catch (Exception ex) { }
|
||
MainWindow.Instance.PLC.TurnSpeed(speed);
|
||
MainWindow.Instance.PLC.TurnDirection(direction);
|
||
MainWindow.Instance.PLC.TurnStart(true);
|
||
isLocationing = true;
|
||
btnLocalization.Text = "结束定位";
|
||
btnLocalization.Type = TTypeMini.Warn;
|
||
}
|
||
else
|
||
{
|
||
MainWindow.Instance.PLC.TurnStart(false);
|
||
iptPosition.Text= MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||
isLocationing = false;
|
||
btnLocalization.Text = "开始定位";
|
||
btnLocalization.Type = TTypeMini.Primary;
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 采集
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnAcquisition_Click(object? sender, EventArgs e)
|
||
{
|
||
if (!isCapturing)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(sltCameraName.Text))
|
||
{
|
||
AntdUI.Message.warn(this, $"请选择相机!", autoClose: 3);
|
||
return;
|
||
}
|
||
if (string.IsNullOrWhiteSpace(iptModel.Text))
|
||
{
|
||
AntdUI.Message.warn(this, $"请选择算法!", autoClose: 3);
|
||
return;
|
||
}
|
||
if (string.IsNullOrWhiteSpace(iptBackImg.Text))
|
||
{
|
||
AntdUI.Message.warn(this, $"请选择背景图片!", autoClose: 3);
|
||
return;
|
||
}
|
||
|
||
// 加载HALCON模型
|
||
if (!File.Exists(iptModel.Text))
|
||
{
|
||
AntdUI.Message.warn(this, $"算法文件不存在!", autoClose: 3);
|
||
return;
|
||
}
|
||
if (!File.Exists(iptBackImg.Text))
|
||
{
|
||
AntdUI.Message.warn(this, $"图片文件不存在!", autoClose: 3);
|
||
return;
|
||
}
|
||
|
||
//获取背景图
|
||
backImage = new HImage();
|
||
backImage.ReadImage(iptBackImg.Text);
|
||
// 从完整路径获取过程名称
|
||
string procedureName = Path.GetFileNameWithoutExtension(iptModel.Text);
|
||
string procedureDir = Path.GetDirectoryName(iptModel.Text);
|
||
|
||
// 重新初始化HALCON引擎
|
||
MyEngine.SetProcedurePath(procedureDir);
|
||
Procedure = new HDevProcedure(procedureName);
|
||
ProcCall = new HDevProcedureCall(Procedure);
|
||
|
||
if (MainWindow.Instance.PLC.Connected)
|
||
{
|
||
//启用视觉定位
|
||
MainWindow.Instance.PLC.VisionPos(true);
|
||
}
|
||
else
|
||
{
|
||
AntdUI.Message.warn(this, $"未连接PLC,无法视觉定位!", autoClose: 3);
|
||
return;
|
||
}
|
||
Do3ThinkCamera=MainWindow.Instance.Cameras.Where(it=>it.CameraName==sltCameraName.Text).FirstOrDefault()??new Do3ThinkCamera();
|
||
Do3ThinkCamera.OnHImageOutput += OnCameraHImageOutput;
|
||
Timer = new System.Threading.Timer(CaptureLoop, null, 0, 50);
|
||
isCapturing = true;
|
||
btnAcquisition.Text = "结束采集";
|
||
btnAcquisition.Type = TTypeMini.Warn;
|
||
}
|
||
else
|
||
{
|
||
if (isLocationing)
|
||
{
|
||
AntdUI.Message.warn(this, $"定位未结束,不能结束采集!", autoClose: 3);
|
||
return;
|
||
}
|
||
|
||
MainWindow.Instance.PLC.VisionPos(false);
|
||
Do3ThinkCamera.OnHImageOutput -= OnCameraHImageOutput;
|
||
Timer?.Dispose();
|
||
isCapturing = false;
|
||
btnAcquisition.Text = "开始采集";
|
||
btnAcquisition.Type = TTypeMini.Primary;
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 触发
|
||
/// </summary>
|
||
/// <param name="state"></param>
|
||
private void CaptureLoop(object? state)
|
||
{
|
||
Do3ThinkCamera.Snapshot();
|
||
}
|
||
|
||
private CancellationTokenSource? _rotateCts;
|
||
private bool _isRotating;
|
||
/// <summary>
|
||
/// 统一旋转控制方法
|
||
/// </summary>
|
||
private async Task RotateControlAsync(bool direction)
|
||
{
|
||
// 防止重复启动
|
||
if (_isRotating) return;
|
||
_isRotating = true;
|
||
|
||
try
|
||
{
|
||
if (!MainWindow.Instance.PLC.Connected)
|
||
{
|
||
this.Invoke(() => AntdUI.Message.warn(this, "未连接PLC!", autoClose: 3));
|
||
return;
|
||
}
|
||
|
||
// 输入验证
|
||
if (string.IsNullOrEmpty(iptSpeed.Text))
|
||
{
|
||
this.Invoke(() => AntdUI.Message.warn(this, "请输入速度!", autoClose: 3));
|
||
return;
|
||
}
|
||
|
||
if (!int.TryParse(iptSpeed.Text, out int speed) || speed <= 0)
|
||
{
|
||
this.Invoke(() => AntdUI.Message.warn(this, "速度必须为正整数!", autoClose: 3));
|
||
return;
|
||
}
|
||
|
||
// 初始化取消令牌
|
||
_rotateCts?.Dispose();
|
||
_rotateCts = new CancellationTokenSource();
|
||
|
||
// 设置PLC参数
|
||
MainWindow.Instance.PLC.TurnSpeed(speed);
|
||
MainWindow.Instance.PLC.TurnDirection(direction);
|
||
MainWindow.Instance.PLC.TurnStart(true);
|
||
|
||
// 异步更新循环
|
||
while (!_rotateCts.IsCancellationRequested)
|
||
{
|
||
var position = MainWindow.Instance.PLC.ReadVisionPos();
|
||
Debug.WriteLine(position.ToString());
|
||
this.BeginInvoke(() => iptPosition.Text = position.ToString());
|
||
await Task.Delay(100, _rotateCts.Token);
|
||
}
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
// 正常取消不处理
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
this.Invoke(() => AntdUI.Message.error(this, $"操作异常:{ex.Message}"));
|
||
}
|
||
finally
|
||
{
|
||
// 确保停止转动
|
||
MainWindow.Instance.PLC.TurnStart(false);
|
||
var finalPos = MainWindow.Instance.PLC.ReadVisionPos();
|
||
this.Invoke(() => iptPosition.Text = finalPos.ToString());
|
||
|
||
_isRotating = false;
|
||
_rotateCts?.Dispose();
|
||
_rotateCts = null;
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 反转抬起
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnReverse_MouseUp(object? sender, MouseEventArgs e)
|
||
{
|
||
_rotateCts?.Cancel();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 反转按下
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private async void BtnReverse_MouseDown(object? sender, MouseEventArgs e)
|
||
{
|
||
await RotateControlAsync(false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 正转抬起
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnForward_MouseUp(object? sender, MouseEventArgs e)
|
||
{
|
||
_rotateCts?.Cancel();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 正转按下
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private async void BtnForward_MouseDown(object? sender, MouseEventArgs e)
|
||
{
|
||
await RotateControlAsync(true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择背景图
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnSelectBackImg_Click(object? sender, EventArgs e)
|
||
{
|
||
using (OpenFileDialog openFileDialog = new OpenFileDialog())
|
||
{
|
||
// 设置对话框标题
|
||
openFileDialog.Title = "选择背景图片";
|
||
// 限制文件后缀为 .hdvp
|
||
openFileDialog.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp";
|
||
// 禁止多选
|
||
openFileDialog.Multiselect = false;
|
||
|
||
// 显示对话框并等待用户操作
|
||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
string filePath = openFileDialog.FileName;
|
||
|
||
iptBackImg.Text = filePath;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择算法
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void BtnSelectModel_Click(object? sender, EventArgs e)
|
||
{
|
||
using (OpenFileDialog openFileDialog = new OpenFileDialog())
|
||
{
|
||
// 设置对话框标题
|
||
openFileDialog.Title = "选择算法文件";
|
||
// 限制文件后缀为 .hdvp
|
||
openFileDialog.Filter = "算法文件 (*.hdvp)|*.hdvp";
|
||
// 禁止多选
|
||
openFileDialog.Multiselect = false;
|
||
|
||
// 显示对话框并等待用户操作
|
||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
string filePath = openFileDialog.FileName;
|
||
|
||
iptModel.Text = filePath;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载事件
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void VisualLocalizationWindow_Load(object? sender, EventArgs e)
|
||
{
|
||
sltDirection.SelectedIndex = 0;
|
||
sltCameraName.Items.Clear();
|
||
if (MainWindow.Instance.Cameras?.Count > 0)
|
||
{
|
||
foreach(var cam in MainWindow.Instance.Cameras)
|
||
{
|
||
sltCameraName.Items.Add(cam.CameraName);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
AntdUI.Message.warn(this, $"未找到启用相机!", autoClose: 3);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 窗体对象实例
|
||
/// </summary>
|
||
private static VisualLocalizationWindow _instance;
|
||
|
||
internal static VisualLocalizationWindow Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null || _instance.IsDisposed)
|
||
_instance = new VisualLocalizationWindow();
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 相机回调
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <param name="camera"></param>
|
||
/// <param name="imageSet"></param>
|
||
private void OnCameraHImageOutput(DateTime dt, CameraBase camera, MatSet imageSet)
|
||
{
|
||
|
||
|
||
|
||
this.BeginInvoke(new MethodInvoker(delegate ()
|
||
{
|
||
|
||
imageViewerControl1.Image = imageSet._mat.ToBitmap();
|
||
if (isLocationing)
|
||
{
|
||
HObject obj = OpenCVHelper.MatToHImage(imageSet._mat);
|
||
HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
|
||
// 调用 ProcCall 的方法
|
||
ProcCall.SetInputIconicParamObject("INPUT_Image", hImage); // 将图像输入Proc
|
||
|
||
ProcCall.SetInputIconicParamObject("BackGroundPic", backImage);
|
||
|
||
ProcCall.SetInputCtrlParamTuple("DistThreshold", Convert.ToInt32(iptThreshold.Text));
|
||
ProcCall.Execute();
|
||
double nNUm = ProcCall.GetOutputCtrlParamTuple("OUTPUT_Flag");
|
||
|
||
if (nNUm == 0)
|
||
{
|
||
MainWindow.Instance.PLC.TurnStart(false);
|
||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||
isLocationing = false;
|
||
btnLocalization.Text = "开始定位";
|
||
btnLocalization.Type = TTypeMini.Primary;
|
||
}
|
||
}
|
||
}));
|
||
|
||
}
|
||
}
|
||
|
||
}
|