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");
}
}
///
/// 保存图像
///
///
///
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);
}
}
}
///
/// 定位
///
///
///
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;
}
}
///
/// 采集
///
///
///
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;
}
}
///
/// 触发
///
///
private void CaptureLoop(object? state)
{
Do3ThinkCamera.Snapshot();
}
///
/// 反转抬起
///
///
///
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);
}
}
///
/// 反转按下
///
///
///
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);
}
}
///
/// 正转抬起
///
///
///
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);
}
}
///
/// 正转按下
///
///
///
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);
}
}
///
/// 选择背景图
///
///
///
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;
}
}
}
///
/// 选择算法
///
///
///
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;
}
}
}
///
/// 加载事件
///
///
///
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);
}
}
///
/// 窗体对象实例
///
private static VisualLocalizationWindow _instance;
internal static VisualLocalizationWindow Instance
{
get
{
if (_instance == null || _instance.IsDisposed)
_instance = new VisualLocalizationWindow();
return _instance;
}
}
///
/// 相机回调
///
///
///
///
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();
}
}
}
}