using Aurora; using Aurora.Api; using Aurora.View; using CoreUnit.Control.UserControl.Canvas; using CoreUnit.Scanner.UserControl.ScannerCanvas; using Microsoft.Win32; using OpenCvSharp; using OpenCvSharp.WpfExtensions; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Configuration; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using System.Windows.Media.Imaging; using WeldingCommon.Settings; using WeldingCommon.Utils; using WeldingCommon.Vision.WeldingObjectGenerator; using static CoreUnit.Control.UserControl.Canvas.ZigZag; using WeldingCommon.Vision.WeldingObjectGenerator.PathEditorLibrary; using WeldingCommon.Data; using System.Windows.Forms.VisualStyles; using VisionCommon; using WeldingCommon.Sequences; using System.Xml.XPath; using Point = OpenCvSharp.Point; using Arc = CoreUnit.Control.UserControl.Canvas.Arc; using System.Reactive.Concurrency; using WeldingCommon.Recipes; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; using Aurora.Api.Devices; using MilUI; using Matrox.MatroxImagingLibrary; namespace WeldingCommon.Views { using Path = System.IO.Path; using TPolygon = List; public class UCManualRCCOperationViewModel : NotifyPropertyChangedBase { private readonly Logger Log = new Logger("UCManualRCCOperationViewModel"); public ICommand CMD_VisibleChanged { get; } public ICommand CMD_LoadImage { get; } public ICommand CMD_SaveImage { get; } public ICommand CMD_SaveCSV { get; } // SMW public ICommand CMD_CheckRadiusImage { get; } public ICommand CMD_DetectEdgeImage { get; } public ICommand CMD_GenerateDrawingObject { get; } public ICommand CMD_UpdateRecipeObjectRCC { get; } public ICommand CMD_FindReferenceCenter { get; } public ICommand CMD_SaveOffsetTable { get; } public ICommand CMD_UpdateOffsetTable { get; } public ICommand CMD_SaveCenterRadius { get; } // Inzi, LFW public ICommand CMD_FindReference { get; } public ICommand CMD_FindObjectOffset { get; } public ICommand CMD_UpdateRecipeObject { get; } public ICommand CMD_RecommendEdgeDetectParams { get; } public ICommand CMD_CenterDetectTest { get; } public ICommand CMD_SaveSystemParameter { get; } public ICommand CMD_RunManualRunRCC { get; } public ICommand CMD_StopManualRunRCC { get; } public ICommand CMD_CellGenTypeChanged { get; } private readonly IAuroraEnvironment _Aurora; private SystemParameter _SystemParameter; private ISequence _SeqManualRunRCC; private bool _IsSequenceRunning_ManualRunRCC; public bool IsSequenceRunning_ManualRunRCC { get => _IsSequenceRunning_ManualRunRCC; set => SetProperty(ref _IsSequenceRunning_ManualRunRCC, value); } private WinSequenceDiagram _WinSequenceDiagramManualRunRCC; public ObservableCollection OptionList { get; set; } = new ObservableCollection(); private string _SelectedOption; public string SelectedOption { get { return _SelectedOption; } set { _SelectedOption = value; //OnPropertyChanged(nameof(_SelectedOption)); if (_SelectedOption == "SMW") { IsSelectedOptionSMW = true; IsSelectedOptionInzi = false; IsSelectedOptionLFW = false; IsSelectedOptionKS = false; } else if (_SelectedOption == "Inzi") { IsSelectedOptionSMW = false; IsSelectedOptionInzi = true; IsSelectedOptionLFW = false; IsSelectedOptionKS = false; } else if (_SelectedOption == "LFW") { IsSelectedOptionSMW = false; IsSelectedOptionInzi = false; IsSelectedOptionLFW = true; IsSelectedOptionKS = false; } else if (_SelectedOption == "KS") { IsSelectedOptionSMW = false; IsSelectedOptionInzi = false; IsSelectedOptionLFW = false; IsSelectedOptionKS = true; } else if (_SelectedOption == "Flangeless") { IsSelectedOptionSMW = false; IsSelectedOptionInzi = false; IsSelectedOptionLFW = false; IsSelectedOptionKS = true; } } } private bool _IsSelectedOptionSMW; public bool IsSelectedOptionSMW { get => _IsSelectedOptionSMW; set => SetProperty(ref _IsSelectedOptionSMW, value); } private bool _IsSelectedOptionInzi; public bool IsSelectedOptionInzi { get => _IsSelectedOptionInzi; set => SetProperty(ref _IsSelectedOptionInzi, value); } private bool _IsSelectedOptionLFW; public bool IsSelectedOptionLFW { get => _IsSelectedOptionLFW; set => SetProperty(ref _IsSelectedOptionLFW, value); } private bool _IsSelectedOptionKS; public bool IsSelectedOptionKS { get => _IsSelectedOptionKS; set => SetProperty(ref _IsSelectedOptionKS, value); } private Stopwatch _Stopwatch; private double _ImageWidth; private double _ImageHeight; private string _LoadImagePath; private Mat _OriginImageMat; private Mat _OriginImageMat2; private BitmapSource _OriginImage; private BitmapSource _OriginImage2; public BitmapSource OriginImage { get => _OriginImage; set => SetProperty(ref _OriginImage, value); } private BitmapSource _CroppedImageL; public BitmapSource CroppedImageL { get => _CroppedImageL; set => SetProperty(ref _CroppedImageL, value); } private BitmapSource _CroppedImageR; public BitmapSource CroppedImageR { get => _CroppedImageR; set => SetProperty(ref _CroppedImageR, value); } private Mat _MaskedImageMat; private BitmapSource _MaskedImage; public BitmapSource MaskedImage { get => _MaskedImage; set => SetProperty(ref _MaskedImage, value); } private Mat _ConvertImageMat; private Mat _ConvertImageMat2; private Mat _DetectImageMat; private BitmapSource _ResultImage; public BitmapSource ResultImage { get => _ResultImage; set => SetProperty(ref _ResultImage, value); } private static ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; private List _RecipeDrawObejct; private ObjectGenerator _ObjectGenerator; private double _CVThreshold; public double CVThreshold { get => _CVThreshold; set => SetProperty(ref _CVThreshold, value); } private int _CVShrinkPixel; public int CVShrinkPixel { get => _CVShrinkPixel; set => SetProperty(ref _CVShrinkPixel, value); } private int _CVShrinkPixel2; public int CVShrinkPixel2 { get => _CVShrinkPixel2; set => SetProperty(ref _CVShrinkPixel2, value); } private int _CVShrinkPixel3; public int CVShrinkPixel3 { get => _CVShrinkPixel3; set => SetProperty(ref _CVShrinkPixel3, value); } private int _CVShrinkPixel4; public int CVShrinkPixel4 { get => _CVShrinkPixel4; set => SetProperty(ref _CVShrinkPixel4, value); } private double _Radius; public double Radius { get => _Radius; set => SetProperty(ref _Radius, value); } private int _Margin; public int Margin { get => _Margin; set => SetProperty(ref _Margin, value); } private int _PointNum; public int PointNum { get => _PointNum; set => SetProperty(ref _PointNum, value); } public bool _EnableAutoMissAlign; public bool EnableAutoMissAlign { get => _EnableAutoMissAlign; set => SetProperty(ref _EnableAutoMissAlign, value); } private double _DetectPointPercent; public double DetectPointPercent { get => _DetectPointPercent; set => SetProperty(ref _DetectPointPercent, value); } private double _CVRadiusMargin; public double CVRadiusMargin { get => _CVRadiusMargin; set => SetProperty(ref _CVRadiusMargin, value); } private int _CVThresholdCircle1; public int CVThresholdCircle1 { get => _CVThresholdCircle1; set => SetProperty(ref _CVThresholdCircle1, value); } private int _CVThresholdCircle2; public int CVThresholdCircle2 { get => _CVThresholdCircle2; set => SetProperty(ref _CVThresholdCircle2, value); } private int _CVThresholdCircle3; public int CVThresholdCircle3 { get => _CVThresholdCircle3; set => SetProperty(ref _CVThresholdCircle3, value); } private int _CVThresholdCircle4; public int CVThresholdCircle4 { get => _CVThresholdCircle4; set => SetProperty(ref _CVThresholdCircle4, value); } private int _CVThresholdCircle5; public int CVThresholdCircle5 { get => _CVThresholdCircle5; set => SetProperty(ref _CVThresholdCircle5, value); } private int _CVThresholdCircle6; public int CVThresholdCircle6 { get => _CVThresholdCircle6; set => SetProperty(ref _CVThresholdCircle6, value); } private int _CVThresholdSpiral1; public int CVThresholdSpiral1 { get => _CVThresholdSpiral1; set => SetProperty(ref _CVThresholdSpiral1, value); } private int _CVThresholdSpiral2; public int CVThresholdSpiral2 { get => _CVThresholdSpiral2; set => SetProperty(ref _CVThresholdSpiral2, value); } private int _CVSearchSize; public int CVSearchSize { get => _CVSearchSize; set => SetProperty(ref _CVSearchSize, value); } private int _CVThresholdLine1; public int CVThresholdLine1 { get => _CVThresholdLine1; set => SetProperty(ref _CVThresholdLine1, value); } private int _CVThresholdLine2; public int CVThresholdLine2 { get => _CVThresholdLine2; set => SetProperty(ref _CVThresholdLine2, value); } private int _CVJigSize; public int CVJigSize { get => _CVJigSize; set => SetProperty(ref _CVJigSize, value); } private int _CVMorpIterations; public int CVMorpIterations { get => _CVMorpIterations; set => SetProperty(ref _CVMorpIterations, value); } private int _CVMorpMaskSize; public int CVMorpMaskSize { get => _CVMorpMaskSize; set => SetProperty(ref _CVMorpMaskSize, value); } private double _MILThreshold; public double MILThreshold { get => _MILThreshold; set => SetProperty(ref _MILThreshold, value); } private double _MILFillGapDist; public double MILFillGapDist { get => _MILFillGapDist; set => SetProperty(ref _MILFillGapDist, value); } private double _MILShrinkDist; public double MILShrinkDist { get => _MILShrinkDist; set => SetProperty(ref _MILShrinkDist, value); } private double _CVInnerCircleSize; public double CVInnerCircleSize { get => _CVInnerCircleSize; set => SetProperty(ref _CVInnerCircleSize, value); } private double _CVOuterCircleSize; public double CVOuterCircleSize { get => _CVOuterCircleSize; set => SetProperty(ref _CVOuterCircleSize, value); } private double _DrawObjectDistanceRange; public double DrawObjectDistanceRange { get => _DrawObjectDistanceRange; set => SetProperty(ref _DrawObjectDistanceRange, value); } private double _DrawObjectLengthSumDiffRange; public double DrawObjectLengthSumDiffRange { get => _DrawObjectLengthSumDiffRange; set => SetProperty(ref _DrawObjectLengthSumDiffRange, value); } private double _DrawObjectArcLengthMax; public double DrawObjectArcLengthMax { get => _DrawObjectArcLengthMax; set => SetProperty(ref _DrawObjectArcLengthMax, value); } private double _DrawObjectCenterXYDiffRange; public double DrawObjectCenterXYDiffRange { get => _DrawObjectCenterXYDiffRange; set => SetProperty(ref _DrawObjectCenterXYDiffRange, value); } private int _MaxMinDiffHigh; public int MaxMinDiffHigh { get => _MaxMinDiffHigh; set => SetProperty(ref _MaxMinDiffHigh, value); } private int _MaxMinDiffLow; public int MaxMinDiffLow { get => _MaxMinDiffLow; set => SetProperty(ref _MaxMinDiffLow, value); } private int _CheckCenterDiff; public int CheckCenterDiff { get => _CheckCenterDiff; set => SetProperty(ref _CheckCenterDiff, value); } private int _DistortionCenterDiff; public int DistortionCenterDiff { get => _DistortionCenterDiff; set => SetProperty(ref _DistortionCenterDiff, value); } private bool _IsRepeatEdgeDetectMode; public bool IsRepeatEdgeDetectMode { get => _IsRepeatEdgeDetectMode; set => SetProperty(ref _IsRepeatEdgeDetectMode, value); } private double _CellRadiusOffset; public double CellRadiusOffset { get => _CellRadiusOffset; set => SetProperty(ref _CellRadiusOffset, value); } private Point _CenterPoint; private Point[][] _MaxContour; private Point[][] _MaxContour2; private UnitPoint _DetectedContourCenter; private UnitPoint _DetectedContourCenter2; private List _DestDrawObjects; private List _DestDrawObjects2; private Point[][] _MinContour; private Point[][] _EdgePoints; private Mat _CroppedImage1; private Mat _CroppedImage2; private List _Paths; private List _Paths2; private List _SelectedArcs; private Arc.eDirection _DrawArcDirection; private string CellType = "Single"; private int _Ref_X, _Ref_Y; private double _Ref_T; private double _ReferenceX; public double ReferenceX { get => _ReferenceX; set => SetProperty(ref _ReferenceX, value); } private double _ReferenceY; public double ReferenceY { get => _ReferenceY; set => SetProperty(ref _ReferenceY, value); } private double _ReferenceTheta; public double ReferenceTheta { get => _ReferenceTheta; set => SetProperty(ref _ReferenceTheta, value); } private double _Offset_X, _Offset_Y, _Offset_T; private double _OffsetX; public double OffsetX { get => _OffsetX; set => SetProperty(ref _OffsetX, value); } private double _OffsetY; public double OffsetY { get => _OffsetY; set => SetProperty(ref _OffsetY, value); } private double _OffsetTheta; public double OffsetTheta { get => _OffsetTheta; set => SetProperty(ref _OffsetTheta, value); } private UnitPoint _ObjectCenter; // Support ContourCorrectionInfoList Selection. private ObservableCollection _SelectedContourCorrectionInfoList = new ObservableCollection(); public ObservableCollection SelectedContourCorrectionInfoList { get => _SelectedContourCorrectionInfoList; set => SetProperty(ref _SelectedContourCorrectionInfoList, value); } private ObservableCollection _ContourCorrectionInfoList = new ObservableCollection(); public ObservableCollection ContourCorrectionInfoList { get => _ContourCorrectionInfoList; set => SetProperty(ref _ContourCorrectionInfoList, value); } private bool _IsOffsetTypeManual; public bool IsOffsetTypeManual { get => _IsOffsetTypeManual; set { SetProperty(ref _IsOffsetTypeManual, value); if (_IsOffsetTypeManual == true) { _ObjectGenerator.SetOffsetType("Manual"); } else { _ObjectGenerator.SetOffsetType("Table"); } } } public class ContourCorrectionInfo { public int Index { get; set; } public float VisionX { get; set; } public float VisionY { get; set; } //public int ScannerX { get; set; } //public int ScannerY { get; set; } } private string _VisionType = "OpenCV"; private List _PathItemList; /////////////////////////////////////////////////////////////// private bool _IsArcByAngle; public bool IsArcByAngle { get => _IsArcByAngle; set => SetProperty(ref _IsArcByAngle, value); } private string _ObjectGenType = "Auto"; private double _MergeDist; public double MergeDist { get => _MergeDist; set => SetProperty(ref _MergeDist, value); } private uint _MaxArcRadius; public uint MaxArcRadius { get => _MaxArcRadius; set => SetProperty(ref _MaxArcRadius, value); } private uint _LineTolerance; public uint LineTolerance { get => _LineTolerance; set => SetProperty(ref _LineTolerance, value); } private uint _ArcTolerance; public uint ArcTolerance { get => _ArcTolerance; set => SetProperty(ref _ArcTolerance, value); } private float _LineDefualtWidth; public float LineDefualtWidth { get => _LineDefualtWidth; set => SetProperty(ref _LineDefualtWidth, value); } private int _ObjectNumber; public int ObjectNumber { get => _ObjectNumber; set => SetProperty(ref _ObjectNumber, value); } public UCManualRCCOperationViewModel(IAuroraEnvironment aurora) { _Aurora = aurora; _SystemParameter = aurora.SettingEntry[CommonSettingIds.SystemParameter] as SystemParameter; _SeqManualRunRCC = _Aurora.SequenceEntry[CommonSequenceIds.SeqManualRunRCC]; IsSequenceRunning_ManualRunRCC = false; CMD_LoadImage = new DelegateCommand(PerformCmdLoadImage); CMD_SaveImage = new DelegateCommand(PerformCmdSaveImage); CMD_SaveCSV = new DelegateCommand(PerformCmdSaveCSV); // SMW CMD_CheckRadiusImage = new DelegateCommand(PerformCmdCheckRadiusImage); CMD_DetectEdgeImage = new DelegateCommand(PerformCmdDetectEdgeImage); CMD_GenerateDrawingObject = new DelegateCommand(PerformCmdGenerateDrawingObject); CMD_UpdateRecipeObjectRCC = new DelegateCommand(PerformCmdUpdateRecipeObjectRCC); CMD_FindReferenceCenter = new DelegateCommand(PerfomCmdFindReferenceCenter); CMD_SaveOffsetTable = new DelegateCommand(PerformCmdSaveOffsetTable); CMD_UpdateOffsetTable = new DelegateCommand(PerformCmdUpdateOffsetTable); CMD_SaveCenterRadius = new DelegateCommand(PerformCmdSaveCenterRadius); // Inzi, LFW CMD_FindReference = new DelegateCommand(PerformCmdFindReference); CMD_FindObjectOffset = new DelegateCommand(PerformCmdFindObjectOffset); CMD_UpdateRecipeObject = new DelegateCommand(PerformCmdUpdateRecipeObject); CMD_RecommendEdgeDetectParams = new DelegateCommand(PerformCmdRecommendEdgeDetectParams); CMD_CenterDetectTest = new DelegateCommand(PerformCmdCenterDetectTest); CMD_SaveSystemParameter = new DelegateCommand(PerformCmdSaveSystemParameter); CMD_RunManualRunRCC = new DelegateCommand(PerformCmdRunManualRunRCC); CMD_StopManualRunRCC = new DelegateCommand(PerformCmdStopManualRunRCC); CMD_CellGenTypeChanged = new DelegateCommand(OnCellGenTypeChanged); InitVariable(); } private void InitVariable() { _Stopwatch = new Stopwatch(); OptionList = new ObservableCollection { "SMW", "Inzi", "LFW", "KS", "Flangeless" }; SelectedOption = OptionList[3]; var pixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; _ObjectGenerator = new ObjectGenerator(pixelResolution); if (_SystemParameter.OffsetType == eOffsetType.manual) { _ObjectGenerator.SetOffsetType("Manual"); } else { _ObjectGenerator.SetOffsetType("CSV"); } if (_SystemParameter.OffsetCSVFile != null) { _ObjectGenerator.SetOffsetTable(_SystemParameter.OffsetCSVFile, _SystemParameter.LensMagnification, _SystemParameter.CameraPixelSize); } else { Log.W("Not exist CSV OffsetTable of Systemparameter"); } // EdgeDetect Param CVThreshold = _SystemParameter.CVThreshold; //CVMorpIterations = _SystemParameter.CVMorpIterations; //CVMorpMaskSize = _SystemParameter.CVMorpMaskSize; CVShrinkPixel = _SystemParameter.CVShrinkPixel; CVShrinkPixel2 = _SystemParameter.CVShrinkPixel2; CVShrinkPixel3 = _SystemParameter.CVShrinkPixel3; CVShrinkPixel4 = _SystemParameter.CVShrinkPixel4; Radius = _SystemParameter.Radius; Margin = _SystemParameter.Margin; PointNum = _SystemParameter.PointNum; DetectPointPercent = _SystemParameter.DetectPointPercent; // % CVJigSize = _SystemParameter.CVJigSize; //CVInnerCircleSize = _SystemParameter.CVInnerCircleSize; // mm //CVOuterCircleSize = _SystemParameter.CVOuterCircleSize; // mm EnableAutoMissAlign = _SystemParameter.EnableAutoMissAlign; // GenObject Param ObjectNumber = _SystemParameter.ObjectNumber; MergeDist = _SystemParameter.dMergeDist; MaxArcRadius = _SystemParameter.nMaxArcRadius; LineTolerance = _SystemParameter.nLineTolerance; ArcTolerance = _SystemParameter.nArcTolerance; LineDefualtWidth = _SystemParameter.fLineDefualtWidth; // DrawObejct Interlock Param DrawObjectDistanceRange = _SystemParameter.DrawObjectDistanceRange; // mm DrawObjectLengthSumDiffRange = _SystemParameter.DrawObjectLengthSumDiffRange; // mm DrawObjectArcLengthMax = _SystemParameter.DrawObjectArcLengthMax; // mm DrawObjectCenterXYDiffRange = _SystemParameter.DrawObjectCenterXYDiffRange; // CheckEdge Param MaxMinDiffHigh = _SystemParameter.MaxMinDiffHigh; MaxMinDiffLow = _SystemParameter.MaxMinDiffLow; CheckCenterDiff = _SystemParameter.CheckCenterDiff; DistortionCenterDiff = _SystemParameter.DistortionCenterDiff; //KS RCC Param CVThresholdCircle1 = _SystemParameter.CVThresholdCircle1; CVThresholdCircle2 = _SystemParameter.CVThresholdCircle2; CVThresholdCircle3 = _SystemParameter.CVThresholdCircle3; CVThresholdCircle4 = _SystemParameter.CVThresholdCircle4; CVThresholdCircle5 = _SystemParameter.CVThresholdCircle5; CVThresholdSpiral1= _SystemParameter.CVThresholdSpiral1; CVThresholdSpiral2= _SystemParameter.CVThresholdSpiral2; //CVThresholdCircle6 = _SystemParameter.CVThresholdCircle6; //CVThresholdCircle2_1 = _SystemParameter.CVThresholdCircle2_1; //CVThresholdCircle2_2 = _SystemParameter.CVThresholdCircle2_2; //CVThresholdCircle2_3 = _SystemParameter.CVThresholdCircle2_3; //CVThresholdCircle2_4 = _SystemParameter.CVThresholdCircle2_4; //CVThresholdCircle2_5 = _SystemParameter.CVThresholdCircle2_5; //CVThresholdCircle2_6 = _SystemParameter.CVThresholdCircle2_6; CVThresholdLine1 = _SystemParameter.CVThresholdLine1; CVThresholdLine2 = _SystemParameter.CVThresholdLine2; CVRadiusMargin = _SystemParameter.CVRadiusMargin; CVSearchSize = _SystemParameter.CVSearchSize; CellRadiusOffset = 0.35; IsOffsetTypeManual = true; } private void OnCellGenTypeChanged(object obj) { CellType = (string)obj; } private void PerformCmdLoadImage(object obj) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = true; if (dialog.ShowDialog() == true) { if (dialog.FileNames.Length == 0) { return; } } else { MessageUtil.ShowWarningToast("Failed to open dialog."); return; } _LoadImagePath = dialog.FileNames[0]; // OpenCV #region OpenCV _OriginImageMat = Cv2.ImRead(_LoadImagePath); OriginImage = _OriginImageMat.ToBitmapSource(); _ConvertImageMat = _OriginImageMat.Clone(); _ObjectGenerator.SetImageSize(_OriginImageMat.Width, _OriginImageMat.Height); _ImageWidth = _OriginImageMat.Width; _ImageHeight = _OriginImageMat.Height; _MaskedImageMat = _ObjectGenerator.MaskingImage(_ConvertImageMat, CVInnerCircleSize, CVOuterCircleSize); MaskedImage = _MaskedImageMat.ToBitmapSource(); if (dialog.FileNames.Length > 1) { _OriginImageMat2 = Cv2.ImRead(dialog.FileNames[1]); _OriginImage2 = _OriginImageMat2.ToBitmapSource(); _ConvertImageMat2 = _OriginImageMat2.Clone(); _MaskedImageMat = _OriginImageMat2.Clone(); MaskedImage = _OriginImageMat2.ToBitmapSource(); } #endregion #region MIL, 미사용 주석 처리 ////buffer 설정, buffer 사이즈는 가져온 이미지의 사이즈로 넣어줘야함.. //MIL.MbufAllocColor(MilEnvironment.Instance.GetSystem(_cameraAgent._CamConfig.CamConnConfig.BoardSlotPos), 3, loadImg.Width, loadImg.Height, 8 + MIL.M_UNSIGNED, MIL.M_IMAGE + MIL.M_DISP + MIL.M_PROC, ref MILImage); ////이미지 로드 //MIL.MbufLoad(imagepath, MILImage); ////WPF Bitmapsource로 변환 //int width = (int)MIL.MbufInquire(MILImage, MIL.M_SIZE_X, MIL.M_NULL); //int height = (int)MIL.MbufInquire(MILImage, MIL.M_SIZE_Y, MIL.M_NULL); ////int stride = width; // Assuming 8-bit grayscale image //int stride = width * 3; // Assuming 24-bit BRG image //byte[] imageData = new byte[width * height * 3]; ////MIL.MbufGet(MILImage, imageData); // 8-bit일 경우 사용 //MIL.MbufGetColor(MILImage, MIL.M_PACKED + MIL.M_BGR24, MIL.M_ALL_BANDS, imageData); ////8-bit 1ch gray일 경우 사용 ////BitmapSource bitmapSource = BitmapSource.Create( //// width, height, 96, 96, System.Windows.Media.PixelFormats.Gray8, null, imageData, stride); ////32-bit 3ch bgr //BitmapSource bitmapSource = BitmapSource.Create( // width, height, 96, 96, System.Windows.Media.PixelFormats.Bgr24, null, imageData, stride); ////Convert bitmapsource to Mat //ConvImg = bitmapSource.ToMat(); //// MIL 해제 //MIL.MbufFree(MILImage); #endregion //int width = loadImg.Width; //int height = loadImg.Height; //int stride = width * 3; //byte[] imageData = new byte[width * height * 3]; //imageData = loadImg.ToBytes(); //BitmapSource bitmapSource = BitmapSource.Create( // loadImg.Width, loadImg.Height, 96, 96, System.Windows.Media.PixelFormats.Bgr24, null, loadImg.Data, loadImg.Step()); //ConvImg = bitmapSource.ToMat(); // WPF Image 컨트롤에 설정 //OriginImage = bitmapSource; } private void PerformCmdSaveImage(object obj) { SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "JPEG Image|*.jpg|PNG Image|*.png|Bitmap Image|*.bmp"; saveFileDialog.Title = "Save an Image File"; saveFileDialog.DefaultExt = "jpg"; // 기본 확장자를 설정합니다. saveFileDialog.FileName = string.Format($"ResultImage_{DateTime.Now.Month}_{DateTime.Now.Day}_{DateTime.Now.ToString("HHmmss")}.jpg"); // 기본 파일 이름을 설정합니다. if (saveFileDialog.ShowDialog() == true) { string savePath = saveFileDialog.FileName; //bitmapSource를 이미지 파일로 저장 BitmapEncoder encoder = new JpegBitmapEncoder(); using (FileStream stream = new FileStream(savePath, FileMode.Create)) { encoder.Frames.Add(BitmapFrame.Create(ResultImage)); encoder.Save(stream); } } else { MessageUtil.ShowWarningToast("Failed to open dialog."); } } private void PerformCmdSaveCSV(object obj) { if (_MaxContour != null) { SaveContoursToCsv(_MaxContour); } //Jin : 미사용 //switch (_VisionType) { // case "OpenCV": // if (_MaxContour != null) { // SaveContoursToCsv(_MaxContour); // } else { // SaveCenterToCsv(_CenterX, _CenterY); // } // break; // case "MIL": // SaveCoordinatesToCsv(_XCoordinates, _YCoordinates); // break; //} } private void SaveContoursToCsv(Point[][] maxcotours) { string folderPath = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "EdgeContour", "Manual"); string filepath = Path.Combine(folderPath, string.Format($"EdgeContour_{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}_{DateTime.Now:HHmmss}.csv")); try { if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } using (StreamWriter writer = new StreamWriter(filepath)) { int index = 0; writer.WriteLine("Index,X_pixel,Y_pixel,X_mm,Y_mm"); foreach (var contour in maxcotours) { foreach (var point in contour) { index++; double convertX = (point.X - _ImageWidth / 2) * (_SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000; double convertY = (-point.Y + _ImageHeight / 2) * (_SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000; writer.WriteLine($"{index},{point.X},{point.Y},{convertX},{convertY}"); } } } } catch (Exception e) { Log.E(e.Message); } } private void SaveCenterToCsv(double centerX, double centerY) { string savepath = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "EdgeContour", "Manual", string.Format($"CenterDetect_{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}.csv")); try { if (!File.Exists(savepath)) { using (StreamWriter writer = new StreamWriter(savepath, false)) { writer.WriteLine("DateTime, CenterX, CenterY"); writer.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}, {centerX}, {centerY}"); } } else { using (StreamWriter writer = new StreamWriter(savepath, true)) { writer.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}, {centerX}, {centerY}"); } } } catch (Exception e) { Log.E(e.Message); } } private void PerformCmdCheckRadiusImage(object obj) { if (_ConvertImageMat == null) { MessageUtil.CreateAndShowMessageDialog("Detect Edge is failed.", "Detect Edge is failed. Please Load image."); return; } var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; _RecipeDrawObejct = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; _Stopwatch.Start(); if (CellType == "Single") { var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvertImageMat); int radius_Pixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); var (right, left, top) = _ObjectGenerator.FindCenterPoint(_ConvertImageMat, CVThreshold, out Point centerPoint, centerX, centerY, CVJigSize); _Stopwatch.Stop(); Log.I($"CheckRadius Complete Time : {(float)_Stopwatch.ElapsedMilliseconds}msec"); _Stopwatch.Reset(); DrawCenterPointRadius(centerPoint, radius_Pixel, right, left, top); } else if (CellType == "Multi") { // 시퀀스에서 동시처리하려면 어차피 변수를 분리해야니깐 Manual에서도 변수하나로 두번처리하는것보다 변수 두개로 가져가자 var (centerX, centerY, centerX2, centerY2) = FindCenterReicpeMultiArc(_ConvertImageMat); int radius_Pixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); int cropWidth = 3200; int cropHeight = 3200; _CroppedImage1 = CropImage(_ConvertImageMat, centerX, centerY, cropWidth, cropHeight); _CroppedImage2 = CropImage(_ConvertImageMat, centerX2, centerY2, cropWidth, cropHeight); CroppedImageL = _CroppedImage1.ToBitmapSource(); CroppedImageR = _CroppedImage2.ToBitmapSource(); var (right, left, top) = _ObjectGenerator.FindCenterPoint(_CroppedImage1, CVThreshold, out Point centerPoint, centerX, centerY, CVJigSize); var (right2, left2, top2) = _ObjectGenerator.FindCenterPoint(_CroppedImage2, CVThreshold, out Point centerPoint2, centerX2, centerY2, CVJigSize); _Stopwatch.Stop(); Log.I($"CheckRadius Complete Time : {(float)_Stopwatch.ElapsedMilliseconds}msec"); _Stopwatch.Reset(); // 크롭된 이미지의 좌표를 원본 이미지의 좌표로 변환 Point centerPointInOriginal = new Point(centerPoint.X + centerX - cropWidth / 2, centerPoint.Y + centerY - cropHeight / 2); Point centerPoint2InOriginal = new Point(centerPoint2.X + centerX2 - cropWidth / 2, centerPoint2.Y + centerY2 - cropHeight / 2); Point rightInOriginal = new Point(right.X + centerX - cropWidth / 2, right.Y + centerY - cropHeight / 2); Point leftInOriginal = new Point(left.X + centerX - cropWidth / 2, left.Y + centerY - cropHeight / 2); Point topInOriginal = new Point(top.X + centerX - cropWidth / 2, top.Y + centerY - cropHeight / 2); Point right2InOriginal = new Point(right2.X + centerX2 - cropWidth / 2, right2.Y + centerY2 - cropHeight / 2); Point left2InOriginal = new Point(left2.X + centerX2 - cropWidth / 2, left2.Y + centerY2 - cropHeight / 2); Point top2InOriginal = new Point(top2.X + centerX2 - cropWidth / 2, top2.Y + centerY2 - cropHeight / 2); Point[] center_points = { centerPointInOriginal, centerPoint2InOriginal }; Point[] right_points = { rightInOriginal, right2InOriginal }; Point[] left_points = { leftInOriginal, left2InOriginal }; Point[] top_points = { topInOriginal, top2InOriginal }; DrawCenterPointRadiusMulti(center_points, radius_Pixel, right_points, left_points, top_points); } } private void DrawCenterPointRadius(Point center_point, double radius, Point right, Point left, Point top) { // Draw the contour on the image _DetectImageMat = _ConvertImageMat.Clone(); Cv2.Circle(_DetectImageMat, center_point, 8, new Scalar(0, 255, 0), -1); Cv2.Circle(_DetectImageMat, center_point, (int)radius, new Scalar(0, 255, 0), 2); Cv2.Circle(_DetectImageMat, right, 5, new Scalar(0, 0, 255), -1); Cv2.Circle(_DetectImageMat, left, 5, new Scalar(0, 0, 255), -1); Cv2.Circle(_DetectImageMat, top, 5, new Scalar(0, 0, 255), -1); ResultImage = _DetectImageMat.ToBitmapSource(); } private void DrawCenterPointRadiusMulti(Point[] center_points, double radius, Point[] right_points, Point[] left_points, Point[] top_points) { // Draw the contour on the image _DetectImageMat = _ConvertImageMat.Clone(); for (int i = 0; i < center_points.Length; i++) { Cv2.Circle(_DetectImageMat, center_points[i], 8, new Scalar(255, 0, 0), -1); Cv2.Circle(_DetectImageMat, center_points[i], (int)radius, new Scalar(0, 255, 0), 2); } for (int i = 0; i < right_points.Length; i++) { Cv2.Circle(_DetectImageMat, right_points[i], 5, new Scalar(0, 0, 255), -1); Cv2.Circle(_DetectImageMat, left_points[i], 5, new Scalar(0, 0, 255), -1); Cv2.Circle(_DetectImageMat, top_points[i], 5, new Scalar(0, 0, 255), -1); } ResultImage = _DetectImageMat.ToBitmapSource(); } private void PerformCmdDetectEdgeImage(object obj) { if (_ConvertImageMat == null) { MessageUtil.CreateAndShowMessageDialog("Detect Edge is failed.", "Detect Edge is failed. Please Load image."); return; } var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; _RecipeDrawObejct = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; int[] shrinkList = new int[] { CVShrinkPixel, CVShrinkPixel2, CVShrinkPixel3, CVShrinkPixel4 }; //Interlock Property에 Edgedetect MaxMinDiff가 포함되어있기때문에 EdgeDetect 함수에서 실행할 수 있도록 한다 _ObjectGenerator.SetInterlockProperties(DrawObjectDistanceRange, DrawObjectArcLengthMax, DrawObjectLengthSumDiffRange, DrawObjectCenterXYDiffRange, MaxMinDiffHigh, MaxMinDiffLow, CheckCenterDiff, DistortionCenterDiff, _SystemParameter.AutoMissAlignHigh, _SystemParameter.AutoMissAlignLow); if (CellType == "Single") { var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvertImageMat); _Stopwatch.Start(); int radius_Pixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); if (!_ObjectGenerator.FindEdge(_ConvertImageMat, radius_Pixel, Margin, PointNum, CVThreshold, centerX, centerY, DetectPointPercent, CVJigSize, out Point[][] maxContour, out _DetectedContourCenter)) { MessageUtil.CreateAndShowMessageDialog("Find Edge", "Fail to find Edge. Check Interlock log."); Log.W(string.Format("Failed to find Edge.")); return; } if (_ObjectGenerator.CheckEdge(maxContour, shrinkList, _ConvertImageMat.Height, _ConvertImageMat.Height, centerX, centerY, EnableAutoMissAlign, out _MaxContour) == 3) { Log.W(string.Format("Failed to check Edge.")); MessageUtil.CreateAndShowMessageDialog("Check Edge", "Fail to check Edge. Check Interlock log."); return; } _Stopwatch.Stop(); Log.I($"EdgeDetect Time : {(float)_Stopwatch.ElapsedMilliseconds} msec"); _Stopwatch.Reset(); // Temp : MaxContour의 Center로부터 MaxContour까지의 거리 평균을 구하자 // contourCenter 픽셀을 Int로 변환해서 쓰면 FindEdge의 ConvertDrawingObjectAxis함수의 center랑 동일하게 나옴.. int로 변환하지않으면 픽셀에 소수점까지 있어서 센터가 바뀌긴함 Point2f contourCenter = _ObjectGenerator.CalculateCentroid(_MaxContour[0]); var temp1 = ((long)contourCenter.X - _ImageWidth / 2) * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; var temp2 = (_ImageHeight / 2 - (long)contourCenter.Y) * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; Log.I($"CenterX : {temp1.ToString("F2")} mm, CenterY : {temp2.ToString("F2")} mm"); double[] radius_list = new double[_MaxContour[0].Count()]; for (int i = 0; i < _MaxContour[0].Count(); i++) { var radius_i = Math.Sqrt((contourCenter.X - _MaxContour[0][i].X) * (contourCenter.X - _MaxContour[0][i].X) + (contourCenter.Y - _MaxContour[0][i].Y) * (contourCenter.Y - _MaxContour[0][i].Y)); radius_list[i] = radius_i; } var radius_list_avg = radius_list.Average(); var radius_final = radius_list_avg * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; // 측정 반지름과 Recipe의 Page에 설정된 Arc Radius와 비교하여 가장 근사한 Radius를 가진 페이지를 선택한다 int closestLayerIndex = -1; double minDifference = double.MaxValue; var recipelayersCnt = _ScannerCanvasUserCtrl.Model.Layers.Count(); //List> layerObjectsLists = new List>(); for (int i = 0; i < recipelayersCnt; i++) { var layerObjects = _ScannerCanvasUserCtrl.Model.Layers[i].Objects; Arc closestArc = null; foreach (var item in layerObjects) { if (item is Arc arc) { closestArc = arc; break; } } if (closestArc != null) { // 본 시퀀스에서는 CellRadiusOffset을 Model에서 받아온다. double difference = Math.Abs(closestArc.Radius - (radius_final - CellRadiusOffset)); if (difference < minDifference) { minDifference = difference; closestLayerIndex = i; } } } _RecipeDrawObejct = _ScannerCanvasUserCtrl.Model.Layers[closestLayerIndex].Objects; Log.I($"Selected Recipe PageNo : {closestLayerIndex + 1}, Detected Radius : {radius_final.ToString("F3")} mm, Model CellRadiusOffset : {CellRadiusOffset} mm"); _Stopwatch.Stop(); Log.I($"Calculate Radius and Fit RecipeDrawObejct Time : {(float)_Stopwatch.ElapsedMilliseconds} msec"); //------------------------------------------------------------------ UpdateDateCorrection(_MaxContour); DrawCVEdgeContour(_MaxContour); } else if (CellType == "Multi") { // 시퀀스에서 동시처리하려면 어차피 변수를 분리해야니깐 Manual에서도 변수하나로 두번처리하는것보다 변수 두개로 가져가자 Stopwatch sw = Stopwatch.StartNew(); var (centerX, centerY, centerX2, centerY2) = FindCenterReicpeMultiArc(_ConvertImageMat); int radius_Pixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); // 현재 FindEdge 알고리즘은 변수로 넣어주는 이미지에서 외곽부터 들어오면서 3점을 찾으니깐 이미지 넣어줄때부터 잘라서 넣어줘야함.. // CenterPixel값을 찾아뒀으니 CenterPixel기준으로 이미지를 자르는게 나을듯(임시로 구현해보고 나중에 좋은방법을 찾아보자) // TODO : Center기준으로 Crop사이즈를 지정하니깐 이미지가 짤리는 부분에서 흑백과 본이미지 경계가 구분되어 EdgeDetect시 JigSize가 필수로 있어야함..아니면 3점을 못찾음 int cropWidth = 3200; int cropHeight = 3200; int cropWidthHalf = cropWidth / 2; int cropHeightHalf = cropHeight / 2; _CroppedImage1 = CropImage(_ConvertImageMat, centerX, centerY, cropWidth, cropHeight); _CroppedImage2 = CropImage(_ConvertImageMat, centerX2, centerY2, cropWidth, cropHeight); sw.Stop(); Log.I($"Crop Complte Time : {(float)sw.ElapsedMilliseconds} msec"); CroppedImageL = _CroppedImage1.ToBitmapSource(); CroppedImageR = _CroppedImage2.ToBitmapSource(); //// Temp //ResultImage = _CroppedImage1.ToBitmapSource(); //ResultImage = croppedImage2.ToBitmapSource(); //obj = null; //SaveImage(obj); sw.Restart(); //여기서 CenterX, Y값은 위에서찾은 centerX,Y를 CroppedImage의 사이즈로 변경해줄 필요가있음 //위에서 Center 기준으로 cropWidth, cropHeight 기준으로 잘랐으니깐 그거 절반이 Center네.. if (!_ObjectGenerator.FindEdge(_CroppedImage1, radius_Pixel, Margin, PointNum, CVThreshold, cropWidthHalf, cropHeightHalf, DetectPointPercent, CVJigSize, out Point[][] maxContour, out _DetectedContourCenter)) { MessageUtil.CreateAndShowMessageDialog("Find Edge", "Fail to find Edge. Check Interlock log."); Log.W(string.Format("Failed to find Edge.")); return; } if (_ObjectGenerator.CheckEdge(maxContour, shrinkList, _CroppedImage1.Height, _CroppedImage1.Width, cropWidthHalf, cropHeightHalf, EnableAutoMissAlign, out _MaxContour) == 3) { MessageUtil.CreateAndShowMessageDialog("Check Edge", "Fail to check Edge. Check Interlock log."); Log.W(string.Format("Failed to check Edge.")); return; } // TODO : _DetectedContourCenter가 CroppedImage의 Center mm 값으로바뀌네.. 전체 Convimge 좌표 기준으로 변경해줘야 함.. // _DetectedContourCenter를 Pixel로 변경 _ObjectGenerator.ConvertPixelAxisFromDrawingObjectAxis(_DetectedContourCenter, _CroppedImage1.Width, _CroppedImage1.Height, out double detectedContourCenterPixelX, out double detectedContourCenterPixelY); // CropImage의 CenterPixel을 원본이미지 Pixel로 변경 detectedContourCenterPixelX += centerX - cropWidthHalf; detectedContourCenterPixelY += centerY - cropHeightHalf; // 원본이미지 Pixel을 다시 _DetectedContourCenter로 바꿔줌 _ObjectGenerator.ConvertDrawingObjectAxis((long)detectedContourCenterPixelX, (long)detectedContourCenterPixelY, _ConvertImageMat.Width, _ConvertImageMat.Height, out _DetectedContourCenter); _MaxContour = ConvertMaxContourPixel(_MaxContour, centerX, centerY, cropWidthHalf, cropHeightHalf); sw.Stop(); Log.I($"First EdgeDetect Time : {(float)sw.ElapsedMilliseconds} msec"); sw.Restart(); if (!_ObjectGenerator.FindEdge(_CroppedImage2, radius_Pixel, Margin, PointNum, CVThreshold, cropWidthHalf, cropHeightHalf, DetectPointPercent, CVJigSize, out maxContour, out _DetectedContourCenter2)) { Log.W(string.Format("Failed to find Edge.")); return; } if (_ObjectGenerator.CheckEdge(maxContour, shrinkList, _CroppedImage2.Height, _CroppedImage2.Width, cropWidthHalf, cropHeightHalf, EnableAutoMissAlign, out _MaxContour2) == 3) { Log.W(string.Format("Failed to check Edge.")); return; } _ObjectGenerator.ConvertPixelAxisFromDrawingObjectAxis(_DetectedContourCenter2, _CroppedImage2.Width, _CroppedImage2.Height, out double detectedContourCenterPixelX2, out double detectedContourCenterPixelY2); detectedContourCenterPixelX2 += centerX2 - cropWidthHalf; detectedContourCenterPixelY2 += centerY2 - cropHeightHalf; _ObjectGenerator.ConvertDrawingObjectAxis((long)detectedContourCenterPixelX2, (long)detectedContourCenterPixelY2, _ConvertImageMat.Width, _ConvertImageMat.Height, out _DetectedContourCenter2); _MaxContour2 = ConvertMaxContourPixel(_MaxContour2, centerX2, centerY2, cropWidthHalf, cropHeightHalf); sw.Stop(); Log.I($"Second EdgeDetect Time : {(float)sw.ElapsedMilliseconds} msec"); sw.Reset(); DrawCVEdgeContourMulti(_MaxContour, _MaxContour2); } } private Point[][] ConvertMaxContourPixel(Point[][] maxContour, int centerX, int centerY, int cropWidthHalf, int cropHeightHalf) { if (maxContour[0].Count() < 1) { Log.E("MaxContour is Null"); return null; } for (int i = 0; i < maxContour[0].Length; i++) { maxContour[0][i].X += (centerX - cropWidthHalf); maxContour[0][i].Y += (centerY - cropHeightHalf); } return maxContour; } private Mat CropImage(Mat sourceImage, int centerX, int centerY, int width, int height) { // 잘라낼 영역의 시작 좌표 계산 int startX = centerX - width / 2; int startY = centerY - height / 2; // 잘라낼 영역의 끝 좌표 계산 int endX = startX + width; int endY = startY + height; // 이미지의 경계를 벗어나지 않도록 조정 startX = Math.Max(startX, 0); startY = Math.Max(startY, 0); endX = Math.Min(endX, sourceImage.Width); endY = Math.Min(endY, sourceImage.Height); // 잘라낼 영역의 크기 계산 int cropWidth = endX - startX; int cropHeight = endY - startY; // 잘라낸 이미지 생성 Rect cropRect = new Rect(startX, startY, cropWidth, cropHeight); Mat croppedImage = new Mat(sourceImage, cropRect); return croppedImage; } private (int centerX, int centerY) FindCenterReicpeSingleArc(Mat image) { int centerX = 0, centerY = 0; foreach (var item in _RecipeDrawObejct) { if (item is Arc) { Arc arc = (Arc)item; centerX = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Width / 2); centerY = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Height / 2); break; } } return (centerX, centerY); } private (int centerX, int centerY, int centerX2, int centerY2) FindCenterReicpeMultiArc(Mat image) { int centerX = 0, centerY = 0, centerX2 = 0, centerY2 = 0; //Recipe에 그려진 Arc의 Center를 가져오기 위해 좌측과 우측의 Arc 순서가 고정되어있어야함 //item에서 LeftArc, RigthArc가 각 1,2번으로 고정되어 있어야 함 int arcCount = 1; foreach (var item in _RecipeDrawObejct) { if (item is Arc) { Arc arc = (Arc)item; if (arcCount == 1) { centerX = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Width / 2); centerY = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Height / 2); } else if (arcCount == 2) { centerX2 = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Width / 2); centerY2 = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Height / 2); break; } arcCount++; } } return (centerX, centerY, centerX2, centerY2); } private void UpdateDateCorrection(Point[][] maxContours) { if (maxContours.Count() < 1) { return; } if (ContourCorrectionInfoList.Count() != 0) { ContourCorrectionInfoList.Clear(); } // MaxContour가 0일 경우 예외처리 if (_MaxContour[0].Count() < 1) { Log.E("MaxContour is Null"); return; } int index = 0; foreach (var contour in maxContours) { foreach (var point in contour) { ContourCorrectionInfo contourCorrectionInfo = new ContourCorrectionInfo(); contourCorrectionInfo.Index = index++; contourCorrectionInfo.VisionX = point.X; contourCorrectionInfo.VisionY = point.Y; ContourCorrectionInfoList.Add(contourCorrectionInfo); } } } private void DrawCVEdgeContour(Point[][] maxContour) { // Draw the contour on the image _DetectImageMat = _ConvertImageMat.Clone(); // MaxContour가 0일 경우 예외처리 if (maxContour[0].Count() < 1) { ResultImage = _DetectImageMat.ToBitmapSource(); //Log.E("MaxContour is Null"); return; } Cv2.DrawContours(_DetectImageMat, maxContour, -1, new Scalar(0, 255, 0), 2); ResultImage = _DetectImageMat.ToBitmapSource(); } private void DrawCVEdgeContourMulti(Point[][] maxContour, Point[][] maxContour2) { // Draw the contour on the image _DetectImageMat = _ConvertImageMat.Clone(); // MaxContour가 0일 경우 예외처리 if (maxContour[0].Count() < 1 && maxContour2[0].Count() < 1) { ResultImage = _DetectImageMat.ToBitmapSource(); //Log.E("MaxContour is Null"); return; } Cv2.DrawContours(_DetectImageMat, maxContour, -1, new Scalar(0, 255, 0), 2); Cv2.DrawContours(_DetectImageMat, maxContour2, -1, new Scalar(0, 255, 0), 2); ResultImage = _DetectImageMat.ToBitmapSource(); } private void PerformCmdGenerateDrawingObject(object obj) { var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; _RecipeDrawObejct = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; // cellType에 따라 처리 // _DestDrawObjects는 RecipeUpdate시 필요, Paths는 ResultImage에 그리기위해 2개로 분리 if (CellType == "Single") { ProcessDrawingObject(eArcCount.FirstArc, _MaxContour, out _DestDrawObjects, out _Paths); } else if (CellType == "Multi") { ProcessDrawingObject(eArcCount.FirstArc, _MaxContour, out _DestDrawObjects, out _Paths); ProcessDrawingObject(eArcCount.SecondArc, _MaxContour2, out _DestDrawObjects2, out _Paths2); } DrawObject(CellType); } private bool ProcessDrawingObject(eArcCount arcCount, Point[][] maxContour, out List destDrawObjects, out List paths) { destDrawObjects = new List(); paths = new List(); Stopwatch sw = Stopwatch.StartNew(); if (!_ObjectGenerator.GetArcInfoFromRecipe(_RecipeDrawObejct, out _SelectedArcs)) return false; // MaxContour가 0일 경우 예외처리 if (maxContour[0].Count() < 1 || maxContour == null) { Log.E("MaxContour is Null"); return false; } if (arcCount == eArcCount.FirstArc) { _ObjectGenerator.SetPolygonFromList(maxContour, out TPolygon polygon); if (IsArcByAngle) { _ObjectGenerator.CalculateAutoPathAngle(_ConvertImageMat, _SelectedArcs[0], polygon, MergeDist, ObjectNumber, _DetectedContourCenter, out _Paths); } else { _ObjectGenerator.CalculateAutoPath(_ConvertImageMat, _SelectedArcs[0], polygon, MergeDist, MaxArcRadius, LineTolerance, ArcTolerance, _DetectedContourCenter, out _Paths); } _ObjectGenerator.ConvertPathItemToDrawingObjects(_Paths, LineDefualtWidth, _ConvertImageMat, _SelectedArcs[0], out destDrawObjects); if (_ObjectGenerator.CheckInterlockDrawingObjectPosition(destDrawObjects, _DetectedContourCenter, _SelectedArcs[0]) == false) { MessageUtil.CreateAndShowMessageDialog("Interlock GenObject", "Interlock Object Generating. Check Interlock Condition."); } } else { _ObjectGenerator.SetPolygonFromList(maxContour, out TPolygon polygon); if (IsArcByAngle) { _ObjectGenerator.CalculateAutoPathAngle(_ConvertImageMat, _SelectedArcs[1], polygon, MergeDist, ObjectNumber, _DetectedContourCenter2, out _Paths2); } else { _ObjectGenerator.CalculateAutoPath(_ConvertImageMat, _SelectedArcs[1], polygon, MergeDist, MaxArcRadius, LineTolerance, ArcTolerance, _DetectedContourCenter2, out _Paths2); } _ObjectGenerator.ConvertPathItemToDrawingObjects(_Paths2, LineDefualtWidth, _ConvertImageMat, _SelectedArcs[1], out destDrawObjects); if (_ObjectGenerator.CheckInterlockDrawingObjectPosition(destDrawObjects, _DetectedContourCenter2, _SelectedArcs[1]) == false) { MessageUtil.CreateAndShowMessageDialog("Interlock GenObject", "Interlock Object Generating. Check Interlock Condition."); } } sw.Stop(); Log.I($"ArcCount : {arcCount}, GenerateWeldingObject Time : {sw.ElapsedMilliseconds} msec"); _ObjectGenerator.SaveDrawingObjectsToCSV(destDrawObjects, "Manual"); //objGenerator.GetAutoPath(out paths); return true; } private void DrawObject(string cellType) { if (_Paths == null) return; _DetectImageMat = _ConvertImageMat.Clone(); void DrawPaths(List paths, Arc originArc) { foreach (var item in paths) { if (item != null) { if (item.GetType() == PathItem._PathType.Line) { Point P1; Int64 P1X, P1Y; Point P2; Int64 P2X, P2Y; item.GetStart(out P1X, out P1Y); P1.X = Convert.ToInt32(P1X); P1.Y = Convert.ToInt32(P1Y); item.GetEnd(out P2X, out P2Y); P2.X = Convert.ToInt32(P2X); P2.Y = Convert.ToInt32(P2Y); Cv2.Line(_DetectImageMat, P1, P2, new Scalar(0, 0, 255), 6); } else if (item.GetType() == PathItem._PathType.Arc) { Point P1; Int64 P1X, P1Y; Point P2; Int64 P2X, P2Y; item.GetStart(out P1X, out P1Y); P1.X = Convert.ToInt32(P1X); P1.Y = Convert.ToInt32(P1Y); item.GetEnd(out P2X, out P2Y); P2.X = Convert.ToInt32(P2X); P2.Y = Convert.ToInt32(P2Y); Point PCenter; Int64 PX, PY; item.GetCenter(out PX, out PY); PCenter.X = Convert.ToInt32(PX); PCenter.Y = Convert.ToInt32(PY); double radius = Convert.ToDouble(item.GetRadius()); double dStartAngle = Math.Atan2((P1.Y - PCenter.Y), (P1.X - PCenter.X)) * (180 / Math.PI); double dEndAngle = Math.Atan2((P2.Y - PCenter.Y), (P2.X - PCenter.X)) * (180 / Math.PI); //if (objGenerator.m_OriginArc); if (dStartAngle < 0) dStartAngle += 360; if (dEndAngle < 0) dEndAngle += 360; //if (PCenter.X < 0 || PCenter.Y < 0 || radius < 1000 || radius > 3000) //{ // Cv2.Line(detectImg, P1, P2, new Scalar(0, 0, 255), 5); // continue; //} //if (dStartAngle < 90 && dEndAngle > 270) dEndAngle -= 360; //if (dStartAngle > 270 && dEndAngle < 90) dStartAngle -= 360; Arc.eDirection drawDirection = originArc.Direction; if (drawDirection == Arc.eDirection.CW) { if (dEndAngle < dStartAngle) dEndAngle += 360; } else { if (dStartAngle < dEndAngle) dStartAngle += 360; } Cv2.Ellipse(_DetectImageMat, PCenter, new Size(radius, radius), 0, dStartAngle, dEndAngle, new Scalar(0, 0, 255), 6); } } } } if (cellType == "Single") { DrawPaths(_Paths, _SelectedArcs[0]); } else if (cellType == "Multi") { DrawPaths(_Paths, _SelectedArcs[0]); if (_Paths2 != null) { DrawPaths(_Paths2, _SelectedArcs[1]); } } ResultImage = _DetectImageMat.ToBitmapSource(); } private void PerfomCmdFindReferenceCenter(object obj) { _SystemParameter = _Aurora.SettingEntry[CommonSettingIds.SystemParameter] as SystemParameter; var X_sum = 0.0; var Y_sum = 0.0; var cnt = 0; OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = true; if (ofd.ShowDialog() == false || ofd.FileNames.Length == 0) { MessageUtil.ShowWarningToast("Failed to open dialog or no selected items."); return; } int Radius_Pixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvertImageMat); foreach (String file in ofd.FileNames) { _OriginImageMat = Cv2.ImRead(file); //if (_SystemParameter.OffsetType == eOffsetType.manual) // _ObjectGenerator.SetOffsetType("Manual"); //if (_SystemParameter.OffsetType == eOffsetType.CSV) // _ObjectGenerator.SetOffsetType("CSV"); _ObjectGenerator.FindEdge(_OriginImageMat, Radius_Pixel, Margin, 3600, CVThreshold, centerX, centerY, DetectPointPercent, CVJigSize, out Point[][] maxContour, out _DetectedContourCenter); X_sum += _DetectedContourCenter.X; Y_sum += _DetectedContourCenter.Y; cnt += 1; } _SystemParameter.ReferenceX = Math.Round(X_sum / cnt, 3); _SystemParameter.ReferenceY = Math.Round(Y_sum / cnt, 3); _Aurora.SettingEntry.Save(CommonSettingIds.SystemParameter, _SystemParameter, "FindReferenceCneter"); Log.I($"Reference CenterX : {_SystemParameter.ReferenceX}, Reference CenterY : {_SystemParameter.ReferenceY}"); } private void PerformCmdUpdateRecipeObjectRCC(object obj) { var result = MessageUtil.ShowYesNoMessageDialog("RCC", "Update the RCC object in the Recipe?"); if (result == false) { return; } UpdateRecipeObjectRCC(); } private void UpdateRecipeObjectRCC() { // Recipe 에서 볼수 있도록 한 임시 함수. // 저장누르면 recipe 가 바뀌므로 주의 // Recipe 의 Layer 0번을 받아온다 var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; List recipeDrawObjects = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; if (CellType == "Single") { _ObjectGenerator.ReplaceRCCObject(eArcCount.FirstArc, recipeDrawObjects, _DestDrawObjects, _DetectedContourCenter); } else { _ObjectGenerator.ReplaceRCCObject(eArcCount.FirstArc, recipeDrawObjects, _DestDrawObjects, _DetectedContourCenter); _ObjectGenerator.ReplaceRCCObject(eArcCount.SecondArc, recipeDrawObjects, _DestDrawObjects2, _DetectedContourCenter2); } _ScannerCanvasUserCtrl.Update(); mainPage.UpdateObjetsInTreeView(); } private void PerformCmdSaveOffsetTable(object obj) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = true; if (dialog.ShowDialog() == false || dialog.FileNames.Length == 0) { MessageUtil.ShowWarningToast("Failed to open dialog or no selected items."); return; } var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; Point2f objectCenter = new Point2f(1, 1); double radius = 0; int centerX = 0, centerY = 0; foreach (var item in _ScannerCanvasUserCtrl.Model.Layers[0].Objects) { if (item is Arc) { Arc arc = (Arc)item; objectCenter = new Point2f((float)(_ImageWidth / 2 + arc.Center.X * _SystemParameter.LensMagnification / _SystemParameter.CameraPixelSize * 1000.0), (float)(_ImageHeight / 2 - arc.Center.Y * _SystemParameter.LensMagnification / _SystemParameter.CameraPixelSize * 1000.0)); radius = arc.Radius * _SystemParameter.LensMagnification / _SystemParameter.CameraPixelSize * 1000.0; centerX = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageWidth / 2); centerY = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageHeight / 2); break; } } int radiusPixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); int imgCount = 0; double[] offset_list = new double[3600]; double[] theta_list = new double[3600]; foreach (String file in dialog.FileNames) { Point[][] edgePointList; _OriginImageMat = Cv2.ImRead(file); if (_SystemParameter.OffsetType == eOffsetType.CSV) { _ObjectGenerator.SetOffsetType("Manual"); } int[] shrinkList = new int[] { 0, 0, 0, 0 }; _ObjectGenerator.FindEdge(_ConvertImageMat, radiusPixel, Margin, 3600, CVThreshold, centerX, centerY, DetectPointPercent, CVJigSize, out Point[][] maxContour, out _DetectedContourCenter); _ObjectGenerator.CheckEdge(maxContour, shrinkList, _ConvertImageMat.Height, _ConvertImageMat.Width, centerX, centerY, _SystemParameter.EnableAutoMissAlign, out edgePointList); if (_SystemParameter.OffsetType == eOffsetType.CSV) { _ObjectGenerator.SetOffsetType("CSV"); } if (edgePointList[0].Length != 3600) { Log.E($"Failed to Find 3600 points in {file}"); MessageUtil.CreateAndShowMessageDialog("Error", $"Failed to Find 3600 points in {file}"); return; } Point2f contourCenter = _ObjectGenerator.CalculateCentroid(edgePointList[0]); //var d = Math.Sqrt((contourCenter.X - objectCenter.X) * (contourCenter.X - objectCenter.X) + (contourCenter.Y - objectCenter.Y) * (contourCenter.Y - objectCenter.Y)); //double theta2 = 0; //if (objectCenter.X > contourCenter.X && objectCenter.Y >= contourCenter.Y) { // theta2 = Math.Atan((objectCenter.Y - contourCenter.Y) / (objectCenter.X - contourCenter.X)); //} else if (objectCenter.X > contourCenter.X && objectCenter.Y <= contourCenter.Y) { // theta2 = Math.Atan((-objectCenter.Y + contourCenter.Y) / (objectCenter.X - contourCenter.X)); //} else if (objectCenter.X <= contourCenter.X && objectCenter.Y < contourCenter.Y) { // theta2 = Math.Atan((contourCenter.X - objectCenter.X) / (contourCenter.Y - objectCenter.Y)); //} else { // theta2 = Math.Atan((contourCenter.X - objectCenter.X) / (objectCenter.Y - contourCenter.Y)); //} for (int i = 0; i < 3600; i++) { //double theta = 0; //double theta1 = 0.1 * i * Math.PI / 180; //theta_list[i] = 0.1 * i; //if (edgePointList[0][i].X > contourCenter.X && edgePointList[0][i].Y >= contourCenter.Y) { // if (objectCenter.X > contourCenter.X && objectCenter.Y >= contourCenter.Y) { // theta = Math.Max(theta1 - theta2, theta2 - theta1); // } else if (objectCenter.X > contourCenter.X && objectCenter.Y <= contourCenter.Y) { // theta = theta1 + theta2; // } else if (objectCenter.X <= contourCenter.X && objectCenter.Y < contourCenter.Y) { // theta = Math.PI / 2 + theta1 + theta2; // if (theta > Math.PI) theta = 2 * Math.PI - theta; // } else { // theta = theta2 + Math.PI / 2 - theta1; // } //} else if (edgePointList[0][i].X > contourCenter.X && edgePointList[0][i].Y <= contourCenter.Y) { // if (objectCenter.X > contourCenter.X && objectCenter.Y >= contourCenter.Y) { // theta = theta1 + theta2; // } else if (objectCenter.X > contourCenter.X && objectCenter.Y <= contourCenter.Y) { // theta = Math.Max(theta1 - theta2, theta2 - theta1); // } else if (objectCenter.X <= contourCenter.X && objectCenter.Y < contourCenter.Y) { // theta = theta2 + Math.PI / 2 - theta1; // } else { // theta = Math.PI / 2 + theta1 + theta2; // if (theta > Math.PI) theta = 2 * Math.PI - theta; // } //} else if (edgePointList[0][i].X <= contourCenter.X && edgePointList[0][i].Y < contourCenter.Y) { // if (objectCenter.X > contourCenter.X && objectCenter.Y >= contourCenter.Y) { // theta = Math.PI / 2 + theta1 + theta2; // if (theta > Math.PI) theta = 2 * Math.PI - theta; // } else if (objectCenter.X > contourCenter.X && objectCenter.Y <= contourCenter.Y) { // theta = theta1 + Math.PI / 2 - theta2; // } else if (objectCenter.X <= contourCenter.X && objectCenter.Y < contourCenter.Y) { // theta = Math.Max(theta1 - theta2, theta2 - theta1); // } else { // theta = Math.PI - theta1 - theta2; // } //} else { // if (objectCenter.X > contourCenter.X && objectCenter.Y >= contourCenter.Y) { // theta = theta1 + Math.PI / 2 - theta2; // } else if (objectCenter.X > contourCenter.X && objectCenter.Y <= contourCenter.Y) { // theta = Math.PI / 2 + theta1 + theta2; // if (theta > Math.PI) theta = 2 * Math.PI - theta; // } else if (objectCenter.X <= contourCenter.X && objectCenter.Y < contourCenter.Y) { // theta = Math.PI - theta1 - theta2; // } else { // theta = Math.Max(theta1 - theta2, theta2 - theta1); // } //} Point nearest_point = new Point(); double min_dist = radiusPixel * radiusPixel; for (int recipe_i = 0; recipe_i < 3600; recipe_i++) { double my_dist = (edgePointList[0][i].X - (objectCenter.X + radius * Math.Cos(recipe_i * Math.PI / 1800))) * (edgePointList[0][i].X - (objectCenter.X + radius * Math.Cos(recipe_i * Math.PI / 1800))); my_dist += (edgePointList[0][i].Y - (objectCenter.Y + radius * Math.Sin(recipe_i * Math.PI / 1800))) * (edgePointList[0][i].Y - (objectCenter.Y + radius * Math.Sin(recipe_i * Math.PI / 1800))); if (my_dist < min_dist) { min_dist = my_dist; nearest_point = new Point(objectCenter.X + radius * Math.Cos(recipe_i * Math.PI / 1800), objectCenter.Y + radius * Math.Sin(recipe_i * Math.PI / 1800)); } } var my_offset_pixel = Math.Sqrt((nearest_point.X - edgePointList[0][i].X) * (nearest_point.X - edgePointList[0][i].X) + (nearest_point.Y - edgePointList[0][i].Y) * (nearest_point.Y - edgePointList[0][i].Y)); var my_offset = my_offset_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; offset_list[i] = (offset_list[i] * imgCount + my_offset) / (imgCount + 1); } imgCount += 1; } SaveOffsetToCsv(offset_list, theta_list); return; } private void SaveOffsetToCsv(double[] offset, double[] theta) { string savepath = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "EdgeContour", "Manual", string.Format($"Offset_{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}_{DateTime.Now.Hour}_{DateTime.Now.Minute}.csv")); try { using (StreamWriter writer = new StreamWriter(savepath)) { writer.WriteLine("Theta,Offset"); for (int i = 0; i < offset.Length; i++) { writer.WriteLine($"{theta[i]},{offset[i]}"); } } MessageUtil.CreateAndShowMessageDialog("Completed", $"Offset table is saved as {savepath}"); } catch (Exception e) { Log.E(e.Message); } } private void PerformCmdUpdateOffsetTable(object obj) { OpenFileDialog dialog = new OpenFileDialog(); string csvPath = ""; if (dialog.ShowDialog() == true) { csvPath = dialog.FileName; if (csvPath == null) { return; } } else { MessageUtil.ShowWarningToast("Failed to open dialog."); return; } _ObjectGenerator.SetOffsetTable(csvPath, _SystemParameter.LensMagnification, _SystemParameter.CameraPixelSize); } private void PerformCmdSaveCenterRadius(object obj) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = true; if (dialog.ShowDialog() == false || dialog.FileNames.Length == 0) { MessageUtil.ShowWarningToast("Failed to open dialog or no selected items."); return; } var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; Point2f objectCenter = new Point2f(1, 1); double radius = 0; int centerX = 0, centerY = 0; foreach (var item in _ScannerCanvasUserCtrl.Model.Layers[0].Objects) { if (item is Arc) { Arc arc = (Arc)item; objectCenter = new Point2f((float)(_ImageWidth / 2 + arc.Center.X * _SystemParameter.LensMagnification / _SystemParameter.CameraPixelSize * 1000.0), (float)(_ImageHeight / 2 - arc.Center.Y * _SystemParameter.LensMagnification / _SystemParameter.CameraPixelSize * 1000.0)); radius = arc.Radius * _SystemParameter.LensMagnification / _SystemParameter.CameraPixelSize * 1000.0; centerX = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageWidth / 2); centerY = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageHeight / 2); break; } } int radiusPixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); int imgCount = 0; double[] centerX_list = new double[dialog.FileNames.Length]; double[] centerY_list = new double[dialog.FileNames.Length]; double[] radiusAvg_list = new double[dialog.FileNames.Length]; foreach (String file in dialog.FileNames) { Point[][] edgePointList; _OriginImageMat = Cv2.ImRead(file); int[] shrinkList = new int[] { 0, 0, 0, 0 }; _ObjectGenerator.FindEdge(_OriginImageMat, radiusPixel, Margin, PointNum, CVThreshold, centerX, centerY, DetectPointPercent, CVJigSize, out Point[][] maxContour, out _DetectedContourCenter); _ObjectGenerator.CheckEdge(maxContour, shrinkList, _OriginImageMat.Height, _OriginImageMat.Width, centerX, centerY, _SystemParameter.EnableAutoMissAlign, out edgePointList); Point2f contourCenter = _ObjectGenerator.CalculateCentroid(edgePointList[0]); var detectedCenterX = ((long)contourCenter.X - _ImageWidth / 2) * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; var detectedCenterY = (_ImageHeight / 2 - (long)contourCenter.Y) * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; double[] radius_list = new double[PointNum]; for (int i = 0; i < PointNum; i++) { var radius_i = Math.Sqrt(((long)contourCenter.X - edgePointList[0][i].X) * ((long)contourCenter.X - edgePointList[0][i].X) + ((long)contourCenter.Y - edgePointList[0][i].Y) * ((long)contourCenter.Y - edgePointList[0][i].Y)); radius_list[i] = radius_i; } var radius_list_avg = radius_list.Average(); var radius_final = radius_list_avg * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0; centerX_list[imgCount] = Math.Round(detectedCenterX, 3); centerY_list[imgCount] = Math.Round(detectedCenterY, 3); radiusAvg_list[imgCount] = Math.Round(radius_final, 3); imgCount++; } SaveCenterRadiusToCsv(centerX_list, centerY_list, radiusAvg_list); return; } private void SaveCenterRadiusToCsv(double[] centerXlist, double[] centerYlist, double[] radiusAvglist) { string savepath = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "EdgeContour", "Manual", string.Format($"CenterRadius_{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}_{DateTime.Now.Hour}_{DateTime.Now.Minute}.csv")); try { using (StreamWriter writer = new StreamWriter(savepath)) { writer.WriteLine("CenterX,CenterY,Radius_Avg"); for (int i = 0; i < centerXlist.Length; i++) { writer.WriteLine($"{centerXlist[i]},{centerYlist[i]},{radiusAvglist[i]}"); } } MessageUtil.CreateAndShowMessageDialog("Completed", $"Offset table is saved as {savepath}"); } catch (Exception e) { Log.E(e.Message); } } private void PerformCmdFindReference(object obj) { if (_ConvertImageMat == null) { MessageUtil.CreateAndShowMessageDialog("Detect Edge is failed.", "Detect Edge is failed. Please Load image."); return; } _DetectImageMat = _ConvertImageMat.Clone(); _Stopwatch.Start(); Point[][] out_contours; double dPixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; double ref_x_mm = 0; double ref_y_mm = 0; double ref_th_deg = 0; int _page_no =CVThresholdCircle1; if (SelectedOption == "KS") { FovInfo _FovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault(); PatternAgentBase _PatternAgent = PatternAgentManager.GetAgent(_FovInfo); var cameraDisplay = CameraDisplayManager.GetDisplay(_FovInfo, eDisplayType.Pattern) as CameraDisplay; int arc_cnt = 6* (_page_no / 2); for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[_page_no].Objects.Count; i += 2) { var item = _ScannerCanvasUserCtrl.Model.Layers[_page_no].Objects[i]; if (item is Arc) { arc_cnt += 1; var procPatternInfo = VisionRecipeManager.GetProcPatternInfo(_FovInfo, $"Arc{(_page_no / 2) + 1}_{arc_cnt-6 * (_page_no / 2)}", (eProcPatternId) arc_cnt-1); var patternInfo = _PatternAgent.GetPatternInfo(_FovInfo, procPatternInfo.PatternId); Log.I($"Finding pattern info procid : Arc{(_page_no / 2) + 1}_{arc_cnt - 6 * (_page_no / 2)}, patternid : {(eProcPatternId)arc_cnt - 1}, {patternInfo}"); UnitPoint center = ((Arc)item).Center; double my_radius = ((Arc)item).Radius; //int roi_height = _PatternAgent.GetFindROI(patternInfo).Height; //int roi_width = _PatternAgent.GetFindROI(patternInfo).Width; int roi_height = 736; int roi_width = 1472; //int roi_height = (int)cameraDisplay.ActualHeight*2; //int roi_width = (int)cameraDisplay.ActualWidth*2; //int roi_height = _PatternAgent.GetFindROI(patternInfo).Height; //int roi_width = _PatternAgent.GetFindROI(patternInfo).Width; Rect my_ROI = new Rect((int)(center.X / dPixelResolution + _DetectImageMat.Width / 2 - roi_width / 2), (int)(_DetectImageMat.Height / 2 - center.Y / dPixelResolution - roi_height / 2), roi_width, roi_height); Mat roi_img = new Mat(_DetectImageMat, my_ROI); Cv2.ImWrite($"D:/test_{arc_cnt}.png", roi_img); Cv2.CvtColor(roi_img, roi_img, ColorConversionCodes.BGR2GRAY); //MIL.MbufAllocColor(MilEnvironment.Instance.GetSystem(_cameraAgent._CamConfig.CamConnConfig.BoardSlotPos), 3, loadImg.Width, loadImg.Height, 8 + MIL.M_UNSIGNED, MIL.M_IMAGE + MIL.M_DISP + MIL.M_PROC, ref mil_roi_img); MIL_ID mil_roi_img = _ObjectGenerator.ConvertMatToMilID(roi_img); //MIL.MbufLoad($"D:/test_{arc_cnt}.png", mil_roi_img); //Mat roi_img_img; //_ObjectGenerator.ConvertMILToMat(mil_roi_img, out roi_img_img); //Cv2.ImWrite($"D:/test_convert_{arc_cnt}.png", roi_img_img); Point2d found_center_pixel, found_center_pixel_mm; PatternResult _PatternResult = _PatternAgent.Find(patternInfo, mil_roi_img, cameraDisplay); MIL.MbufFree(mil_roi_img); if (_PatternResult.Status == eFoundStatus.FoundOK) { Log.W("Pattern is found."); var resultsList = _PatternResult.Results.ToList(); found_center_pixel = new Point2d(resultsList[0].ImagePosition.X + my_ROI.X, resultsList[0].ImagePosition.Y + my_ROI.Y); found_center_pixel_mm = new Point2d((found_center_pixel.X - _DetectImageMat.Width / 2) * dPixelResolution, (_DetectImageMat.Height / 2 - found_center_pixel.Y) * dPixelResolution); UnitPoint offset = new UnitPoint(found_center_pixel_mm.X - center.X, found_center_pixel_mm.Y - center.Y); Log.I($"Offset : {offset.X},{offset.Y}"); Cv2.Circle(_DetectImageMat, new Point(found_center_pixel.X, found_center_pixel.Y), (int)(my_radius / dPixelResolution), Scalar.Red, 8); //Cv2.PutText(_DetectImageMat, resultsList[0].ToString(), new Point(found_center_pixel.X, found_center_pixel.Y), HersheyFonts.HersheySimplex, 2, Scalar.Red); } else { Log.W("Pattern is not found."); } } } ResultImage = _DetectImageMat.ToBitmapSource(); return; //int[] threshold_array = new int[] { CVThresholdCircle1, CVThresholdCircle2, CVThresholdCircle3, CVThresholdCircle4, CVThresholdCircle5, CVThresholdCircle6 }; //_RecipeDrawObejct = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; //if (_RecipeDrawObejct.Count < 13) return; //if (!(_RecipeDrawObejct[12] is Spline)) return; //if (((Spline)_RecipeDrawObejct[12]).Center.Y < 0) // threshold_array = new int[] { _SystemParameter.CVThresholdCircle2_1, _SystemParameter.CVThresholdCircle2_2, _SystemParameter.CVThresholdCircle2_3, _SystemParameter.CVThresholdCircle2_4, _SystemParameter.CVThresholdCircle2_5, _SystemParameter.CVThresholdCircle2_6 }; //int circle_cnt = 0; //for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[0].Objects.Count; i += 2) //{ // var item = _ScannerCanvasUserCtrl.Model.Layers[0].Objects[i]; // if (item is Arc) // { // double my_radius = ((Arc)item).Radius; // UnitPoint center = ((Arc)item).Center; ; // var ROI_X = (center.X - my_radius * 2) / dPixelResolution + _DetectImageMat.Width / 2; // var ROI_Y = -(center.Y + my_radius * 2) / dPixelResolution + _DetectImageMat.Height / 2; // var ROI_size = my_radius * 4 / dPixelResolution; // Point2f circle = _ObjectGenerator.find_circle_center(_DetectImageMat, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, (int)ROI_size, (int)ROI_size), threshold_array[circle_cnt], CVRadiusMargin, my_radius / dPixelResolution); // circle_cnt += 1; // circle = new Point2f((float)(circle.X + ROI_X), (float)(circle.Y + ROI_Y)); // //Point2f circle = _ObjectGenerator.find_circle_center(_DetectImageMat, new OpenCvSharp.Rect(3325, 4250, 500, 500), threshold, my_radius, my_radius / dPixelResolution); // Cv2.Circle(_DetectImageMat, new Point(circle.X, circle.Y), (int)(my_radius / dPixelResolution), Scalar.Red, 8); // circle = new Point2f((float)((circle.X - _DetectImageMat.Width / 2) * dPixelResolution), (float)((-circle.Y + _DetectImageMat.Height / 2) * dPixelResolution)); // UnitPoint offset = new UnitPoint(circle.X - center.X, circle.Y - center.Y); // IDrawObject objclone = item.Clone(); // objclone.Move(offset); // _ScannerCanvasUserCtrl.Model.Layers[0].Objects[i] = objclone; // IDrawObject objclone_line = _ScannerCanvasUserCtrl.Model.Layers[0].Objects[i + 1].Clone(); // objclone_line.Move(offset);/// // _ScannerCanvasUserCtrl.Model.Layers[0].Objects[i + 1] = objclone_line; // } // else if (item is Line) // { // var line_length = Math.Abs(((Line)item).PF1.Y - ((Line)item).PF2.Y); // if (line_length < 2) continue; // int ROI_height = (int)(1.5 * line_length / dPixelResolution); // int ROI_width = (int)(5 / dPixelResolution); // //int ROI_width = (int)(0.8 * line_length / dPixelResolution); // int ROI_X = (int)(((Line)item).PF1.X / dPixelResolution + _DetectImageMat.Width / 2) - ROI_width / 2; // int ROI_Y = (int)(-Math.Max(((Line)item).PF1.Y, ((Line)item).PF2.Y) / dPixelResolution + _DetectImageMat.Height / 2) - ROI_height / 4; // RotatedRect r = _ObjectGenerator.find_line_center(_DetectImageMat, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, (int)(ROI_width), (int)ROI_height), _CVThresholdLine1, _CVThresholdLine2); // Point[] intVertices = new Point[4]; // for (int j = 0; j < 4; j++) // { // intVertices[j] = new Point(r.Points()[j].X + ROI_X, r.Points()[j].Y + ROI_Y); // } // Cv2.Polylines(_DetectImageMat, new Point[][] { intVertices }, true, Scalar.Red, 5); // UnitPoint LineCenter = new UnitPoint((r.Center.X + ROI_X - _DetectImageMat.Width / 2) * dPixelResolution, (-r.Center.Y - ROI_Y + _DetectImageMat.Height / 2) * dPixelResolution); // UnitPoint offset = new UnitPoint(LineCenter.X - (((Line)item).PF1.X + ((Line)item).PF2.X) / 2, LineCenter.Y - (((Line)item).PF1.Y + ((Line)item).PF2.Y) / 2); // IDrawObject objclone = item.Clone(); // float angle = Math.Min(r.Angle, 90 - r.Angle); // objclone.Rotate(angle, LineCenter); // objclone.Move(offset); // _ScannerCanvasUserCtrl.Model.Layers[0].Objects[i] = objclone; // } //} //ResultImage = _DetectImageMat.ToBitmapSource(); //return; } if (SelectedOption == "Flangeless") { OpenCvSharp.Rect[] ROIs = new OpenCvSharp.Rect[4]; Point[] points = new Point[_ScannerCanvasUserCtrl.Model.Layers[0].Objects.Count]; for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[0].Objects.Count; i++) { if (_ScannerCanvasUserCtrl.Model.Layers[0].Objects[i] is Arc) { Arc arc = (Arc)(_ScannerCanvasUserCtrl.Model.Layers[0].Objects[i]); points[i] = new Point(arc.Center.X / dPixelResolution + _DetectImageMat.Width / 2, -arc.Center.Y / dPixelResolution + _DetectImageMat.Height / 2); } } RotatedRect rotatedRect = Cv2.MinAreaRect(points); for (int i = 0; i < 4; i++) ROIs[i] = new Rect((int)rotatedRect.Points()[i].X - 500, (int)rotatedRect.Points()[i].Y - 500, 1000, 1000); ROIs[0] = new Rect(915, 116, 1400, 1400); ROIs[1] = new Rect(8049, 170, 1400, 1400); ROIs[2] = new Rect(964, 3342, 1400, 1400); ROIs[3] = new Rect(8032, 3386, 1400, 1400); var (center, angle, four_points) = _ObjectGenerator.find_rectangle_center(_DetectImageMat, ROIs, 70); _Ref_X = center.X; _Ref_Y = center.Y; _Ref_T = angle; Cv2.Line(_DetectImageMat, new Point(four_points[0].X, four_points[0].Y), new Point(four_points[1].X, four_points[1].Y), Scalar.Red, 3); Cv2.Line(_DetectImageMat, new Point(four_points[0].X, four_points[0].Y), new Point(four_points[3].X, four_points[3].Y), Scalar.Red, 3); Cv2.Line(_DetectImageMat, new Point(four_points[2].X, four_points[2].Y), new Point(four_points[3].X, four_points[3].Y), Scalar.Red, 3); Cv2.Line(_DetectImageMat, new Point(four_points[2].X, four_points[2].Y), new Point(four_points[1].X, four_points[1].Y), Scalar.Red, 3); Cv2.Line(_DetectImageMat, new Point(center.X - 20 * Math.Sin(angle), center.Y - 20 * Math.Cos(angle)), new Point(center.X + 20 * Math.Sin(angle), center.Y + 20 * Math.Cos(angle)), Scalar.Red, 3); Cv2.Line(_DetectImageMat, new Point(center.X - 20 * Math.Sin(angle), center.Y - 20 * Math.Cos(angle)), new Point(center.X + 20 * Math.Sin(angle), center.Y + 20 * Math.Cos(angle)), Scalar.IndianRed, 3); ResultImage = _DetectImageMat.ToBitmapSource(); ref_x_mm = (_Ref_X * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0; ref_y_mm = (_Ref_Y * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0; ref_th_deg = _Ref_T * 180 / Math.PI; ReferenceX = Math.Round(ref_x_mm, 2); ReferenceY = Math.Round(ref_y_mm, 2); ReferenceTheta = ref_th_deg; Log.I($"Center: ({Math.Round(ref_x_mm, 2)}(mm), {Math.Round(ref_y_mm, 2)}(mm)), Theta: {ref_th_deg},"); return; } if (SelectedOption == "LFW") { //ref_x = 2412; ref_y = 1832; _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; foreach (var item in _ScannerCanvasUserCtrl.Model.Layers[0].Objects) { if (item is Arc) { Arc arc = (Arc)item; _Ref_X = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageWidth / 2); _Ref_Y = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageHeight / 2); break; } } } var (_, _, theta, _, cX_pixel, cY_pixel, ScX_pixel, ScY_pixel, radius) = _ObjectGenerator.FindOffset(_ConvertImageMat, CVThreshold, _Ref_X, _Ref_Y, 0, out out_contours, SelectedOption); if (out_contours[0].Length == 0) { Log.E("Failed to Find Objects"); MessageUtil.CreateAndShowMessageDialog("Error", "Failed to Find Objects"); return; } _Stopwatch.Stop(); Log.I($"Elapsed Time : {(float)_Stopwatch.ElapsedMilliseconds}"); Cv2.DrawContours(_DetectImageMat, out_contours, 0, new Scalar(0, 255, 255), 3); if (SelectedOption == "Inzi") { Cv2.Circle(_DetectImageMat, new Point(cX_pixel, cY_pixel), (int)radius, new Scalar(0, 255, 255), 3); RotatedRect rotatedRect = Cv2.MinAreaRect(out_contours[1]); Point2f[] vertices = rotatedRect.Points(); for (int i = 0; i < 4; i++) { Cv2.Line(_DetectImageMat, (Point)vertices[i], (Point)vertices[(i + 1) % 4], new Scalar(0, 255, 0), 2); } Cv2.Circle(_DetectImageMat, new Point(cX_pixel, cY_pixel), 20, new Scalar(0, 0, 255), -1); Cv2.Circle(_DetectImageMat, new Point(ScX_pixel, ScY_pixel), 20, new Scalar(0, 0, 255), -1); } else { int px = ScX_pixel; int py = ScY_pixel; Cv2.Line(_DetectImageMat, new Point(cX_pixel, cY_pixel), new Point(px, py), new Scalar(0, 255, 0), 2); theta = theta * Math.PI / 180; } _Ref_X = cX_pixel; _Ref_Y = cY_pixel; _Ref_T = theta; cX_pixel -= _ConvertImageMat.Width / 2; cY_pixel = (_ConvertImageMat.Height / 2 - cY_pixel); ref_x_mm = (cX_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0; ref_y_mm = (cY_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0; ref_th_deg = theta * 180 / Math.PI; Log.I($"Center: ({Math.Round(ref_x_mm, 2)}(mm), {Math.Round(ref_y_mm, 2)}(mm)), Theta: {ref_th_deg},"); _Stopwatch.Reset(); ResultImage = _DetectImageMat.ToBitmapSource(); //mm로 표시해주기 위해서 Log로 남기는 변수를 띄워준다 ReferenceX = Math.Round(ref_x_mm, 2); ReferenceY = Math.Round(ref_y_mm, 2); ReferenceTheta = ref_th_deg; } private void PerformCmdFindObjectOffset(object obj) { _DetectImageMat = _ConvertImageMat.Clone(); //_ConvMatImage_after = Cv2.ImRead("D:\\Ring_result.png"); double dPixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; if (SelectedOption == "KS") { for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[CVThresholdCircle1].Objects.Count; i++) { var item = _ScannerCanvasUserCtrl.Model.Layers[CVThresholdCircle1].Objects[i]; double my_radius = 0; int ROI_X = 0; int ROI_Y = 0; int ROI_W = 0; int ROI_H = 0; double bead_size1 = 0; double bead_size2 = 0; int search_size = 0; UnitPoint center = new UnitPoint(0, 0); OpenCvSharp.Point p1 = new OpenCvSharp.Point(); OpenCvSharp.Point p2 = new OpenCvSharp.Point(); Point[][] contour; int type = -1; if (item is Arc) { center = ((Arc)item).Center; my_radius = ((Arc)item).Radius; type = 0; ROI_W = 779; ROI_H = 779; ROI_X = (int)(center.X / dPixelResolution) + _ConvertImageMat.Width / 2 - ROI_W/2; ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvertImageMat.Height / 2 - ROI_H / 2; search_size = (int)(ROI_W / 10); //(bead_size1, bead_size2, p1, p2, contour) = _ObjectGenerator.check_bead_size(_ConvertImageMat, _ConvertImageMat, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_H), type, CVSearchSize); int[] bead_size_info = new int[3]; Point[] start_bead_point_info = new Point[3]; Point[] end_bead_point_info = new Point[3]; (bead_size_info, start_bead_point_info, end_bead_point_info, contour) = _ObjectGenerator.check_bead_size(_ConvertImageMat, _ConvertImageMat, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_H), type, search_size); //Cv2.Line(_DetectImageMat, p1, p2, Scalar.LimeGreen, 10); //Cv2.Line(_DetectImageMat, new Point(p1.X, p1.Y+10), new Point(p1.X, p1.Y - 10), Scalar.LimeGreen, 10); //Cv2.Line(_DetectImageMat, new Point(p2.X, p2.Y+10), new Point(p2.X, p2.Y - 10), Scalar.LimeGreen, 10); //Cv2.PutText(_DetectImageMat, $"{Math.Round(bead_size1 * dPixelResolution,3)} mm", new Point(p1.X + 10, p1.Y + 220), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); int min_bead_size = int.MaxValue; int average_bead_size = 0; for (int li = 0; li < bead_size_info.Length; li++) { p1 = start_bead_point_info[li]; p2 = end_bead_point_info[li]; Cv2.Line(_DetectImageMat, p1, p2, Scalar.LimeGreen, 10); if (Math.Abs(p1.X - p2.X) > Math.Abs(p1.Y - p2.Y)) { Cv2.Line(_DetectImageMat, new Point(p1.X, p1.Y + 10), new Point(p1.X, p1.Y - 10), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p2.X, p2.Y + 10), new Point(p2.X, p2.Y - 10), Scalar.LimeGreen, 10); } else { Cv2.Line(_DetectImageMat, new Point(p1.X + 10, p1.Y), new Point(p1.X - 10, p1.Y), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p2.X + 10, p2.Y), new Point(p2.X - 10, p2.Y), Scalar.LimeGreen, 10); } // Cv2.PutText(_DetectImageMat, $"{Math.Round(bead_size_info[li] * dPixelResolution, 3)} mm", new Point(p1.X + 10, p1.Y + 220), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); average_bead_size += bead_size_info[li]; if (min_bead_size > bead_size_info[li]) min_bead_size = bead_size_info[li]; } //Cv2.PutText(_DetectImageMat, $"MIN : {Math.Round(min_bead_size * dPixelResolution, 3)}", new Point(ROI_X - 600, ROI_Y + 800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); //Cv2.PutText(_DetectImageMat, $"AVG : {Math.Round(average_bead_size * dPixelResolution / bead_size_info.Length, 3)}", new Point(ROI_X - 600, ROI_Y + 1000), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); if(_ConvertImageMat.Height / 2 > ROI_Y) { Cv2.PutText(_DetectImageMat, $"1 : {Math.Round(bead_size_info[0] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1200), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"2 : {Math.Round(bead_size_info[1] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1400), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"3 : {Math.Round(bead_size_info[2] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1600), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"4 : {Math.Round(bead_size_info[3] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Log.I($"1:{bead_size_info[0]}, 2:{bead_size_info[1]}, 3:{bead_size_info[2]}, 4:{bead_size_info[3]}"); } else { Cv2.PutText(_DetectImageMat, $"1 : {Math.Round(bead_size_info[0] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 200), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"2 : {Math.Round(bead_size_info[1] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 400), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"3 : {Math.Round(bead_size_info[2] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 600), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"4 : {Math.Round(bead_size_info[3] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Log.I($"1:{bead_size_info[0]}, 2:{bead_size_info[1]}, 3:{bead_size_info[2]}, 4:{bead_size_info[3]}"); } } else if (item is Spline) { center = ((Spline)item).Center; my_radius = ((Spline)item).Radius; type = 1; ROI_W = 492; ROI_X = (int)(center.X / dPixelResolution) + _ConvertImageMat.Width / 2 - ROI_W / 2; ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvertImageMat.Height / 2 - ROI_W / 2; double[] spline_y = new double[3]; spline_y[0] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[CVThresholdCircle1].Objects[0]).Center.Y; spline_y[1] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[CVThresholdCircle1].Objects[1]).Center.Y; spline_y[2] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[CVThresholdCircle1].Objects[2]).Center.Y; Array.Sort(spline_y); int spline_empty_spot_y = (int)(_DetectImageMat.Height / 2 - (spline_y[0] - ((Spline)_ScannerCanvasUserCtrl.Model.Layers[CVThresholdCircle1].Objects[0]).Radius * 1.5) / dPixelResolution); int[] bead_size_info = new int[3]; Point[] start_bead_point_info = new Point[3]; Point[] end_bead_point_info = new Point[3]; (bead_size_info, start_bead_point_info, end_bead_point_info, contour) = _ObjectGenerator.check_bead_size(_ConvertImageMat, _ConvertImageMat, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, spline_empty_spot_y); bead_size1 = bead_size_info[0]; bead_size2 = bead_size_info[1]; p1 = start_bead_point_info[0]; // (bead_size1, bead_size2, p1, p2, contour) = _ObjectGenerator.check_bead_size(_ConvertImageMat, _ConvertImageMat, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, spline_empty_spot_y); Log.I($"Spiral Bead Size : {Math.Round(bead_size1 * dPixelResolution, 3)} mm, {Math.Round(bead_size2 * dPixelResolution, 3)} mm"); Cv2.Line(_DetectImageMat, new Point(p1.X - bead_size1 / 2, p1.Y), new Point(p1.X + bead_size1/2, p1.Y), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p1.X, p1.Y+bead_size2/2), new Point(p1.X, p1.Y-bead_size2/2), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p1.X - bead_size1 / 2, p1.Y+10), new Point(p1.X - bead_size1 / 2, p1.Y-10), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p1.X + bead_size1 / 2, p1.Y + 10), new Point(p1.X + bead_size1 / 2, p1.Y - 10), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p1.X-10,p1.Y-bead_size2/2), new Point(p1.X + 10 / 2, p1.Y - bead_size2 / 2), Scalar.LimeGreen, 10); Cv2.Line(_DetectImageMat, new Point(p1.X-10,p1.Y+bead_size2/2), new Point(p1.X + 10 / 2, p1.Y + bead_size2 / 2), Scalar.LimeGreen, 10); Cv2.PutText(_DetectImageMat, $"W : {Math.Round(bead_size1 * dPixelResolution,3)} mm", new Point(p1.X+bead_size1/2, p1.Y), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); Cv2.PutText(_DetectImageMat, $"H : {Math.Round(bead_size2 * dPixelResolution,3)} mm", new Point(p1.X + bead_size1 / 2, p1.Y +bead_size2/2+50), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); } } ResultImage = _DetectImageMat.ToBitmapSource(); return; } _Stopwatch.Start(); Point[][] out_contours; var (offsetX, offsetY, _, offsetT, cX_pixel, cY_pixel, ScX_pixel, ScY_pixel, radius) = _ObjectGenerator.FindOffset(_ConvertImageMat, CVThreshold, _Ref_X, _Ref_Y, _Ref_T, out out_contours, SelectedOption); if (out_contours[0].Length == 0) { Log.E("Failed to Find Objects"); MessageUtil.CreateAndShowMessageDialog("Error", "Failed to Find Objects"); return; } Cv2.DrawContours(_DetectImageMat, out_contours, 0, new Scalar(0, 255, 255), 3); if (SelectedOption == "Inzi") { Cv2.Circle(_DetectImageMat, new Point(cX_pixel, cY_pixel), (int)radius, new Scalar(0, 255, 255), 3); Cv2.DrawContours(_DetectImageMat, out_contours, 1, new Scalar(0, 255, 255), 3); RotatedRect rotatedRect = Cv2.MinAreaRect(out_contours[1]); Point2f[] vertices = rotatedRect.Points(); for (int i = 0; i < 4; i++) { Cv2.Line(_DetectImageMat, (Point)vertices[i], (Point)vertices[(i + 1) % 4], new Scalar(0, 255, 0), 2); } Cv2.Circle(_DetectImageMat, new Point(cX_pixel, cY_pixel), 20, new Scalar(0, 0, 255), -1); Cv2.Circle(_DetectImageMat, new Point(ScX_pixel, ScY_pixel), 20, new Scalar(0, 0, 255), -1); cX_pixel -= _ConvertImageMat.Width / 2; cY_pixel = (_ConvertImageMat.Height / 2 - cY_pixel); _ObjectCenter = new UnitPoint((cX_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0, (cY_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0); (_Offset_X, _Offset_Y, _Offset_T) = ((offsetX * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0, (offsetY * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0, offsetT); } else { int px = ScX_pixel; int py = ScY_pixel; Cv2.Line(_DetectImageMat, new Point(cX_pixel, cY_pixel), new Point(px, py), new Scalar(0, 255, 0), 2); cX_pixel -= _ConvertImageMat.Width / 2; cY_pixel = (_ConvertImageMat.Height / 2 - cY_pixel); _ObjectCenter = new UnitPoint((cX_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0, (cY_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0); (_Offset_X, _Offset_Y, _Offset_T) = ((offsetX * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0, (offsetY * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0, offsetT); _Offset_T = _Offset_T * Math.PI / 180; } _Stopwatch.Stop(); Log.I($"Elapsed Time : {(float)_Stopwatch.ElapsedMilliseconds}"); Log.I($"Center Offset: ({(float)_Offset_X}(mm), {(float)_Offset_Y}(mm)), Theta Offset: {(float)(_Offset_T * 180 / Math.PI)},"); _Stopwatch.Reset(); ResultImage = _DetectImageMat.ToBitmapSource(); OffsetX = _Offset_X; OffsetY = _Offset_Y; OffsetTheta = _Offset_T * 180 / Math.PI; //deg } private void PerformCmdUpdateRecipeObject(object obj) { var result = MessageUtil.ShowYesNoMessageDialog("Update Recipe", "Update the object in the Recipe?"); if (result == false) { return; } UpdateRecipeObject(); } private void UpdateRecipeObject() { // Recipe 에서 볼수 있도록 한 임시 함수. // 저장누르면 recipe 가 바뀌므로 주의 // Recipe 의 Layer 0번을 받아온다 var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; for (int i = 0; i < (_ScannerCanvasUserCtrl.Model.Layers.Length); i++) { List sourcelist = _ScannerCanvasUserCtrl.Model.Layers[i].Objects; _ObjectGenerator.ReplaceObject(sourcelist, _Offset_X, _Offset_Y, _Offset_T, _ObjectCenter); } _ScannerCanvasUserCtrl.Update(); mainPage.UpdateObjetsInTreeView(); } private void PerformCmdRecommendEdgeDetectParams(object obj) { // 추후 기능 사용시 수정 필요 /* var result = MessageUtil.ShowYesNoMessageDialog("RCC", "Recommend EdgeDetect parameters(Threshold, ShrinkPixel)?"); if (result == false) { return; } // 최소값, 최대값 정해두고 그 안에서 찾자. 이거까지 parameter 로 뺄 필요는 없을듯 // mask image 로 할경우 ConvImg 를 MaskedImg 로 바꿔줄 것 // Pixel의 Center와 Pixel간 거리의 min, max를 구해서 minmax의 차이가 가장 작은 threshold를 추천한다 //double Threshold = 3; // Check Radius를 사용하여 센터의 위치가 맞는 최소값을 기준으로 시작 double Threshold = CVThreshold; int loopcnt = 20; // Threshold 시작부터 cnt 까지 증가하면서 찾는다. Func GetDistance = (x, y) => Math.Sqrt(x * x + y * y); //double range = 9999; //double RecommandedThreshold = 10; double RecommandedThreshold = CVThreshold; double min_dist = 9999; double contour_min_dist = 9999; //List temp_dist = new List(); int centerX = 0, centerY = 0; foreach (var item in _ScannerCanvasUserCtrl.Model.Layers[0].Objects) { if (item is Arc) { Arc arc = (Arc)item; centerX = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageWidth / 2); centerY = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + _ImageHeight / 2); break; } } int Radius_Pixel = (int)(((Radius * _SystemParameter.LensMagnification) / _SystemParameter.CameraPixelSize) * 1000.0); for (int i = 0; i < loopcnt; i++) { //maxContour = objGenerator.ReSizeFindMaxContour(ConvImg, 2, Threshold, CVShrinkPixel); //objGenerator.FindEdge(ConvImg, 1508, 10, 3600, Threshold, CVShrinkPixel, out maxContour); _ObjectGenerator.FindEdge(_ConvertImageMat, Radius_Pixel, Margin, PointNum, Threshold, centerX, centerY, CVShrinkPixel, CVShrinkPixel2, CVShrinkPixel3, CVShrinkPixel4, DetectPointPercent, out _MaxContour); //Point2f centroid = objGenerator.CalculateCentroid(maxContour[0]); //if (Single.IsNaN(centroid.X) || Single.IsNaN(centroid.Y)) continue; // min/max가 아닌 Check Radius를 통해 입력한 Radius 길이로 비교(min_dist) //double min = 9999; //double max = -9999; for (int j = 0; j < _MaxContour[0].Length; j++) { //double dist = GetDistance(maxContour[0][j].X - centroid.X, maxContour[0][j].Y - centroid.Y); // Contour의 무게 중심 기준이 아닌, Check Radius를 토대로 찾은 센터를 기준으로 진행 double dist = GetDistance(_MaxContour[0][j].X - _CenterPoint.X, _MaxContour[0][j].Y - _CenterPoint.Y); //if (dist < min) // min = dist; //if (dist > max) // max = dist; double diff_dist = Math.Abs(Radius_Pixel - dist); if (diff_dist < contour_min_dist) { contour_min_dist = diff_dist; } } //if (range > max - min) //{ // range = max - min; // RecommandedThreshold = Threshold; //} //temp_dist.Add(contour_min_dist); if (min_dist > contour_min_dist) { min_dist = contour_min_dist; RecommandedThreshold = Threshold; } Threshold = Threshold + 1; } CVThreshold = RecommandedThreshold; _ObjectGenerator.FindEdge(_ConvertImageMat, Radius_Pixel, Margin, PointNum, CVThreshold, centerX, centerY, CVShrinkPixel, CVShrinkPixel2, CVShrinkPixel3, CVShrinkPixel4, DetectPointPercent, out _MaxContour); UpdateDateCorrection(_MaxContour); DrawCVEdgeContour(_MaxContour); _ObjectGenerator.SetInterlockProperties(DrawObjectDistanceRange, DrawObjectArcLengthMax, DrawObjectLengthSumDiffRange, DrawObjectCenterXYDiffRange); if (!GetArcInfoFromRecipe()) { return; } //객체 생성 후 객체의 시작점을 기준으로 센터까지의 거리를 구해서 평균 한 후 기존 arc의 반지름과의 차이가 가작 작은 값을 추천한다 int loopShrinkcnt = 60; //double dMinLengthDiff = 9999; double dMinRadiusDiff = 9999; int shrinkPixel = 0; //int Radius_Pixel = (int)(((Radius * _systemParam.LensMagnification) / _systemParam.CameraPixelSize) * 1000.0); for (int i = 0; i < loopShrinkcnt; i++) { //maxContour = objGenerator.ReSizeFindMaxContour(ConvImg, 2, CVThreshold, i); _ObjectGenerator.FindEdge(_ConvertImageMat, Radius_Pixel, Margin, PointNum, CVThreshold, centerX, centerY, CVShrinkPixel, CVShrinkPixel2, CVShrinkPixel3, CVShrinkPixel4, DetectPointPercent, out _MaxContour); if (_VisionType == "OpenCV") { _ObjectGenerator.SetPolygonFromList(_MaxContour); } else { _ObjectGenerator.SetPolygonFromList(_EdgePoints); } _ObjectGenerator.CalculateAutoPath(MergeDist, MaxArcRadius, LineTolerance, ArcTolerance); _ObjectGenerator.ConvertPathItemToDrawingObjects(LineDefualtWidth, out _DestDrawObjectList); _ObjectGenerator.CheckInterlockDrawingObjectPosition(_DestDrawObjectList); // objGenerator.fDetectedContourRadius 는 가장 먼 point 로 Radius 를 구해줘서 ShrinkPixel이 크게 잡힌다. // point 들의 평균이 가장 작은 것으로 고쳐주자. //double radiusdiff = Math.Abs(objGenerator.m_OriginArc.Radius - objGenerator.fDetectedContourRadius); double radiusdiff = 0; List lsPointRadius = new List(); foreach (var item in _DestDrawObjectList) { lsPointRadius.Add(GetDistance((item.PF1.X - _ObjectGenerator.DetectedContourCenter.X), (item.PF1.Y - _ObjectGenerator.DetectedContourCenter.Y))); } radiusdiff = Math.Abs(lsPointRadius.Average() - _ObjectGenerator.m_OriginArc.Radius); if (radiusdiff < dMinRadiusDiff) { dMinRadiusDiff = radiusdiff; shrinkPixel = i; } //double lengthdiff = Math.Abs(objGenerator.m_OriginArc.Length - objGenerator.dPathLengthSum); //if (lengthdiff < dMinLengthDiff) //{ // dMinLengthDiff = lengthdiff; // ShrinkPixel = i; //} } CVShrinkPixel = shrinkPixel; //maxContour = objGenerator.ReSizeFindMaxContour(ConvImg, 2, CVThreshold, CVShrinkPixel); _ObjectGenerator.FindEdge(_ConvertImageMat, Radius_Pixel, Margin, PointNum, CVThreshold, centerX, centerY, CVShrinkPixel, CVShrinkPixel2, CVShrinkPixel3, CVShrinkPixel4, DetectPointPercent, out _MaxContour); UpdateDateCorrection(_MaxContour); DrawCVEdgeContour(_MaxContour); //GenerateDrawingObject(obj); GenerateDrawingObject(); */ } private void PerformCmdCenterDetectTest(object obj) { _MinContour = FindMinContourForCenter(_ConvertImageMat, CVThreshold); DrawCVCenterContour(_MinContour); } private Point[][] FindMinContourForCenter(Mat oriImg, double threshold) { // Convert to grayscale Mat grayImg = new Mat(); Cv2.CvtColor(oriImg, grayImg, ColorConversionCodes.BGR2GRAY); // Apply threshold Mat thresImg = new Mat(); Cv2.Threshold(grayImg, thresImg, threshold, 200, ThresholdTypes.BinaryInv); // Find contours Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(thresImg, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple); //string InvertedImgfilePath = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "EdgeContour", "ImgTest", // string.Format($"InvertedImg{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}.jpg")); //Cv2.ImWrite(InvertedImgfilePath, InvertedImg); int minWidth = 150; int minWSize = int.MaxValue; int minCntNo = 0; for (int i = 0; i < contours.Length; i++) { Rect rect = Cv2.BoundingRect(contours[i]); if (rect.Width < minWidth) { continue; } if (minWSize > rect.Width) { minWSize = rect.Width; minCntNo = i; } } // Create an empty image to draw the minimum contour Mat minCntImg = Mat.Zeros(oriImg.Size(), MatType.CV_8UC1); // Draw the minimum contour Cv2.DrawContours(minCntImg, contours, minCntNo, Scalar.White, -1); // Find the contour again in the drawn image Point[][] minContour; Cv2.FindContours(minCntImg, out minContour, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); return minContour; } private void DrawCVCenterContour(Point[][] minContour) { // Draw the contour on the image _DetectImageMat = _ConvertImageMat.Clone(); Rect minRect = Cv2.BoundingRect(minContour[0]); double centerX = minRect.X + (minRect.Width / 2); double centerY = minRect.Y + (minRect.Height / 2); double mCenterX = (((centerX - _DetectImageMat.Width / 2) * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; double mCenterY = (((_DetectImageMat.Height / 2 - centerY) * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; //_CenterX = mCenterX; //_CenterY = mCenterY; Cv2.DrawContours(_DetectImageMat, minContour, -1, new Scalar(0, 255, 0), 2); Cv2.Line(_DetectImageMat, new Point(centerX - 50, centerY), new Point(centerX + 50, centerY), new Scalar(0, 0, 255), 5); Cv2.Line(_DetectImageMat, new Point(centerX, centerY - 50), new Point(centerX, centerY + 50), new Scalar(0, 0, 255), 5); ResultImage = _DetectImageMat.ToBitmapSource(); MessageUtil.CreateAndShowMessageDialog("Circle Find Success", string.Format("{0:0.00} , {1:0.00}", mCenterX, mCenterY)); } private void PerformCmdSaveSystemParameter(object obj) { var result = MessageUtil.ShowYesNoMessageDialog("RCC", "Save RCC parameters in system parameters?"); if (result == false) { return; } _SystemParameter = _Aurora.SettingEntry[CommonSettingIds.SystemParameter] as SystemParameter; // EdgeDetect Param _SystemParameter.CVThreshold = CVThreshold; _SystemParameter.CVShrinkPixel = CVShrinkPixel; _SystemParameter.CVShrinkPixel2 = CVShrinkPixel2; _SystemParameter.CVShrinkPixel3 = CVShrinkPixel3; _SystemParameter.CVShrinkPixel4 = CVShrinkPixel4; _SystemParameter.Radius = Radius; // mm _SystemParameter.Margin = Margin; // mm _SystemParameter.PointNum = PointNum; // divide count _SystemParameter.DetectPointPercent = DetectPointPercent; // % _SystemParameter.CVJigSize = CVJigSize; _SystemParameter.EnableAutoMissAlign = EnableAutoMissAlign; // GenObejct Param _SystemParameter.ObjectNumber = ObjectNumber; _SystemParameter.dMergeDist = MergeDist; _SystemParameter.nMaxArcRadius = MaxArcRadius; _SystemParameter.nLineTolerance = LineTolerance; _SystemParameter.nArcTolerance = ArcTolerance; _SystemParameter.fLineDefualtWidth = LineDefualtWidth; // DrawObejct Interlock Param _SystemParameter.DrawObjectDistanceRange = DrawObjectDistanceRange; // mm _SystemParameter.DrawObjectLengthSumDiffRange = DrawObjectLengthSumDiffRange; // mm _SystemParameter.DrawObjectArcLengthMax = DrawObjectArcLengthMax; // mm _SystemParameter.DrawObjectCenterXYDiffRange = DrawObjectCenterXYDiffRange; //mm // CheckEdge Param _SystemParameter.MaxMinDiffHigh = MaxMinDiffHigh; _SystemParameter.MaxMinDiffLow = MaxMinDiffLow; _SystemParameter.CheckCenterDiff = CheckCenterDiff; _SystemParameter.DistortionCenterDiff = DistortionCenterDiff; // Reference는 값을 직접 입력하는 것으로 하자 //_SystemParameter.ReferenceX = _Ref_X; //mm //_SystemParameter.ReferenceY = _Ref_Y; //mm //_SystemParameter.ReferenceTh = _Ref_T; //deg //KS RCC _SystemParameter.CVThresholdCircle1 = CVThresholdCircle1; _SystemParameter.CVThresholdCircle2 = CVThresholdCircle2; _SystemParameter.CVThresholdCircle3 = CVThresholdCircle3; _SystemParameter.CVThresholdCircle4 = CVThresholdCircle4; _SystemParameter.CVThresholdCircle5 = CVThresholdCircle5; _SystemParameter.CVThresholdCircle6 = CVThresholdCircle6; _SystemParameter.CVThresholdSpiral1 = CVThresholdSpiral1; _SystemParameter.CVThresholdSpiral2 = CVThresholdSpiral2; _SystemParameter.CVRadiusMargin = CVRadiusMargin; _SystemParameter.CVSearchSize = CVSearchSize; _Aurora.SettingEntry.Save(CommonSettingIds.SystemParameter, _SystemParameter, "ManualRCCOperation"); } // Flying Vision + Detect Image + Generate Object + Welding Sequence Functions private void PerformCmdRunManualRunRCC(object obj) { var result = MessageUtil.ShowYesNoMessageDialog("RCC", "Start ManualRunRCC Sequence?"); if (result == false) { return; } if (VisionRecipeManager.GetFovInfos().Count == 0) { MessageUtil.ShowWarningToast(string.Format("Please check the Vision Recipe of the currently active Recipe.")); return; } if (_SeqManualRunRCC.RunState == SequenceRunState.Running) { MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "SeqManualRunRCC")); return; } var scoutSeqParams = new ScoutSeqParams(VisionRecipeManager.GetFovInfos()[0], eDisplayType.Machine_B); var param = new SeqManualRunRCC_InitParam() { UseStream = false, ScoutSeqParams = scoutSeqParams, }; PopupSequenceDiagram(ref _WinSequenceDiagramManualRunRCC, CommonSequenceIds.SeqManualRunRCC, param); IsSequenceRunning_ManualRunRCC = true; _SeqManualRunRCC.Start(param, OnCompleteManualRunRCC); } private void OnCompleteManualRunRCC(SequenceActionResult res) { if (res != null) { if (res.Param is SeqManualRunRCC_OutParam result && result.Success == true) { //ResultManualRunData // ManualRunRCC 이후 ResultImage 표현하는 건 미사용으로 우선 주석처리한다. 사용시 주석해제 //System.Windows.Application.Current.Dispatcher.Invoke(() => { // AddResultManualRunDataResult(result.ResultManualRunData); //}); IsSequenceRunning_ManualRunRCC = false; MessageUtil.ShowSuccessToast(string.Format("Success SeqManualRunRCC")); CloseSequenceDiagram(_WinSequenceDiagramManualRunRCC); return; } } IsSequenceRunning_ManualRunRCC = false; MessageUtil.ShowWarningToast(string.Format("Fail SeqManualRunRCC")); } private void AddResultManualRunDataResult(ResultManualRunData result) { if (result != null) { _ConvertImageMat = result.ResultImage; _PathItemList = result.PathItemList; } DrawObject(CellType); } private void PerformCmdStopManualRunRCC(object obj) { if (_SeqManualRunRCC.RunState == SequenceRunState.Idle) { return; } IsSequenceRunning_ManualRunRCC = false; _SeqManualRunRCC.Stop(); } private void PopupSequenceDiagram(ref WinSequenceDiagram winSequenceDiagram, string seqId, object param) { if (winSequenceDiagram == null) { winSequenceDiagram = new WinSequenceDiagram(seqId); winSequenceDiagram.Closing += ClosingEvent; winSequenceDiagram.SetParam(new SeqDrawerParam() { SequenceId = seqId, DiagramType = eDiagramType.Tree, LineType = eLineType.Straight, IsShowSubSequence = false, VisibleKeys = new List() }); winSequenceDiagram.Owner = System.Windows.Application.Current.MainWindow; winSequenceDiagram.Width = 600; winSequenceDiagram.SequenceParam = param; winSequenceDiagram.Show(); } else { winSequenceDiagram.SequenceParam = param; winSequenceDiagram.WindowState = System.Windows.WindowState.Normal; winSequenceDiagram.Show(); } } private void CloseSequenceDiagram(WinSequenceDiagram winSequenceDiagram) { System.Windows.Application.Current.Dispatcher.Invoke(() => { if (winSequenceDiagram != null) { winSequenceDiagram.Close(); } }); } private void ClosingEvent(object sender, CancelEventArgs e) { e.Cancel = true; (sender as System.Windows.Window).Hide(); } } }