DHDHSoftware/DHSoftware/Views/VisualLocalizationWindow.cs
2025-04-18 14:03:42 +08:00

494 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AntdUI;
using DH.Commons.Base;
using DH.Commons.Enums;
using DH.Devices.Camera;
using HalconDotNet;
using OpenCvSharp.Extensions;
using Sunny.UI;
using static System.Net.Mime.MediaTypeNames;
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;
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;
}
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.SaveToFile("VisualLocalization.json");
}
}
/// <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();
}
/// <summary>
/// 反转抬起
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnReverse_MouseUp(object? sender, MouseEventArgs e)
{
if (MainWindow.Instance.PLC.Connected)
{
MainWindow.Instance.PLC.TurnStart(false);
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
}
else
{
AntdUI.Message.warn(this, $"未连接PLC", autoClose: 3);
}
}
/// <summary>
/// 反转按下
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnReverse_MouseDown(object? sender, MouseEventArgs e)
{
if (MainWindow.Instance.PLC.Connected)
{
//开启转盘
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(false);
MainWindow.Instance.PLC.TurnStart(true);
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
}
else
{
AntdUI.Message.warn(this, $"未连接PLC", autoClose: 3);
}
}
/// <summary>
/// 正转抬起
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnForward_MouseUp(object? sender, MouseEventArgs e)
{
if (MainWindow.Instance.PLC.Connected)
{
MainWindow.Instance.PLC.TurnStart(false);
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
}
else
{
AntdUI.Message.warn(this, $"未连接PLC", autoClose: 3);
}
}
/// <summary>
/// 正转按下
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnForward_MouseDown(object? sender, MouseEventArgs e)
{
if (MainWindow.Instance.PLC.Connected)
{
//开启转盘
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(true);
MainWindow.Instance.PLC.TurnStart(true);
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
}
else
{
AntdUI.Message.warn(this, $"未连接PLC", autoClose: 3);
}
}
/// <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)
{
imageViewerControl1.Image = imageSet._mat.ToBitmap();
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();
}
}
}
}