using System.Data; using System.Drawing.Imaging; using AntdUI; using DH.Commons.Base; using DH.Commons.Enums; 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 localizations = new List(); 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; try { localizations = VisualLocalization.LoadAll(); } catch { } } private void SltCameraName_SelectedIndexChanged(object sender, IntEventArgs e) { string cameraName= sltCameraName.Text; 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; } } 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(); } } /// /// 保存图像 /// /// /// 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(); } } } }