2026-01-26 18:56:53 +09:00

1985 lines
105 KiB
C#

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 Microsoft.Office.Interop.Excel;
using Point = OpenCvSharp.Point;
using Arc = CoreUnit.Control.UserControl.Canvas.Arc;
using System.Reactive.Concurrency;
using System.Windows.Shapes;
using WeldingCommon.Recipes;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
namespace WeldingCommon.Views
{
using Path = System.IO.Path;
using TPolygon = List<Vision.WeldingObjectGenerator.GeometryLibrary.TPoint>;
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<string> OptionList { get; set; } = new ObservableCollection<string>();
private string _SelectedOption;
public string SelectedOption {
get { return _SelectedOption; }
set {
_SelectedOption = value;
//OnPropertyChanged(nameof(_SelectedOption));
if (_SelectedOption == "SMW") {
IsSelectedOptionSMW = true;
IsSelectedOptionInzi = false;
IsSelectedOptionLFW = false;
} else if (_SelectedOption == "Inzi") {
IsSelectedOptionSMW = false;
IsSelectedOptionInzi = true;
IsSelectedOptionLFW = false;
} else if (_SelectedOption == "LFW") {
IsSelectedOptionSMW = false;
IsSelectedOptionInzi = false;
IsSelectedOptionLFW = 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 Stopwatch _Stopwatch;
private double _ImageWidth;
private double _ImageHeight;
private string _LoadImagePath;
private Mat _OriginImageMat;
private BitmapSource _OriginImage;
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 _DetectImageMat;
private BitmapSource _ResultImage;
public BitmapSource ResultImage { get => _ResultImage; set => SetProperty(ref _ResultImage, value); }
private static ScannerCanvasUserCtrl _ScannerCanvasUserCtrl;
private List<IDrawObject> _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 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<IDrawObject> _DestDrawObjects;
private List<IDrawObject> _DestDrawObjects2;
private Point[][] _MinContour;
private Point[][] _EdgePoints;
private Mat _CroppedImage1;
private Mat _CroppedImage2;
private List<PathItem> _Paths;
private List<PathItem> _Paths2;
private List<Arc> _SelectedArcs;
private Arc.eDirection _DrawArcDirection;
private string CellType = "Single";
private int _Ref_X, _Ref_Y;
private double _Ref_T;
private int _SearchMin;
public int SearchMin { get => _SearchMin; set => SetProperty(ref _SearchMin, value); }
private int _SearchMax;
public int SearchMax { get => _SearchMax; set => SetProperty(ref _SearchMax, value); }
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<ContourCorrectionInfo> _SelectedContourCorrectionInfoList = new ObservableCollection<ContourCorrectionInfo>();
public ObservableCollection<ContourCorrectionInfo> SelectedContourCorrectionInfoList { get => _SelectedContourCorrectionInfoList; set => SetProperty(ref _SelectedContourCorrectionInfoList, value); }
private ObservableCollection<ContourCorrectionInfo> _ContourCorrectionInfoList = new ObservableCollection<ContourCorrectionInfo>();
public ObservableCollection<ContourCorrectionInfo> 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<PathItem> _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<string> { "SMW", "Inzi", "LFW" };
SelectedOption = OptionList[0];
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;
CellRadiusOffset = 0.35;
// EdgeDetect Result Data
SearchMax = _SystemParameter.Serach_Max;
SearchMin = _SystemParameter.Serach_Min;
ReferenceX = _SystemParameter.ReferenceX;
ReferenceY = _SystemParameter.ReferenceY;
ReferenceTheta = _SystemParameter.ReferenceTh;
IsOffsetTypeManual = true;
}
private void OnCellGenTypeChanged(object obj)
{
CellType = (string)obj;
}
private void PerformCmdLoadImage(object obj)
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == true) {
_LoadImagePath = dialog.FileName;
if (_LoadImagePath == null) {
return;
}
} else {
MessageUtil.ShowWarningToast("Failed to open dialog.");
return;
}
// 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();
#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 : {_DetectedContourCenter.X.ToString("F2")} mm, CenterY : {_DetectedContourCenter.Y.ToString("F2")} mm");
var dPixelResolution = _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification / 1000.0;
Point _DetectedContourCenterPixel = new Point(_DetectedContourCenter.X / dPixelResolution + _ConvertImageMat.Width/2, _ConvertImageMat.Height/2 - _DetectedContourCenter.Y / dPixelResolution);
double[] radius_list = new double[_MaxContour[0].Count()];
for(int i = 0; i < _MaxContour[0].Count(); i++) {
//계산중 오버플로우 발생하여 double 캐스팅
var radius_i = Math.Sqrt((double)(_DetectedContourCenterPixel.X- _MaxContour[0][i].X) * (double)(_DetectedContourCenterPixel.X - _MaxContour[0][i].X) + (double)(_DetectedContourCenterPixel.Y- _MaxContour[0][i].Y) * (double)(_DetectedContourCenterPixel.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();
Arc selectedClosestArc = null;
//List<List<IDrawObject>> layerObjectsLists = new List<List<IDrawObject>>();
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;
selectedClosestArc = closestArc;
}
}
}
_RecipeDrawObejct = _ScannerCanvasUserCtrl.Model.Layers[closestLayerIndex].Objects;
Log.I($"Detecte Radius - CellRadiusOffset : {(radius_final - CellRadiusOffset).ToString("F3")} mm, Detected Radius : {radius_final.ToString("F3")} mm, Model CellRadiusOffset : {CellRadiusOffset} mm");
Log.I($"Selected Recipe PageNo : {closestLayerIndex + 1}, Selected Reicpe Arc Radius : {selectedClosestArc.Radius} 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;
}
// maxContour를 Contour로 연결해서 그림
//Cv2.DrawContours(_DetectImageMat, maxContour, -1, new Scalar(0, 255, 0), 2);
// TODO : maxContour를 점으로 표시함
int pointRadius = 3; // Radius of the points
Scalar pointColor = new Scalar(0, 255, 0); // Green color
foreach (var point in maxContour[0]) {
Cv2.Circle(_DetectImageMat, point, pointRadius, pointColor, -1);
}
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<IDrawObject> destDrawObjects, out List<PathItem> paths)
{
destDrawObjects = new List<IDrawObject>();
paths = new List<PathItem>();
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<PathItem> 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<IDrawObject> 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.ShowWarningToast("Not Load Image.");
return;
}
_DetectImageMat = _ConvertImageMat.Clone();
_Stopwatch.Start();
Point[][] out_contours;
//if (SelectedOption == "LFW") {
// //ref_x = 2412; ref_y = 1832;
// var mainPage = WeldingRecipeManager.GetWeldingPage();
// _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;
// }
// }
//}
if (_SearchMin==0 ||_SearchMax==0 || _SearchMin>=_SearchMax) {
MessageUtil.ShowWarningToast(string.Format("Please check the _SearchMin / _SearchMax Value."));
return;
}
var (_, _, theta, _, cX_pixel, cY_pixel, ScX_pixel, ScY_pixel, radius) = _ObjectGenerator.FindOffset(_ConvertImageMat, CVThreshold, _ImageWidth / 2, _ImageHeight / 2, 0, out out_contours, SelectedOption, _SearchMin,_SearchMax);
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);
for (int i=0; i < out_contours[0].Length; i++) {
Cv2.Circle(_DetectImageMat, out_contours[0][i], 3, new Scalar(0, 0, 255), -1);
}
Cv2.Circle(_DetectImageMat, new Point(_ImageWidth / 2, _ImageHeight / 2), _SearchMin, new Scalar(255, 0, 0), 3);
Cv2.Circle(_DetectImageMat, new Point(_ImageWidth / 2, _ImageHeight / 2), _SearchMax, 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);
var ref_x_mm = (cX_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0;
var ref_y_mm = (cY_pixel * _SystemParameter.CameraPixelSize / _SystemParameter.LensMagnification) / 1000.0;
var 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();
_Stopwatch.Start();
Point[][] out_contours;
if (_SearchMin == 0 || _SearchMax == 0 || _SearchMin >= _SearchMax) {
MessageUtil.ShowWarningToast(string.Format("Please check the _SearchMin / _SearchMax Value."));
return;
}
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, _SearchMin, _SearchMax);
if (out_contours[0] == null)
{
MessageUtil.CreateAndShowMessageDialog("Error", "Failed to Find Objects");
return;
}
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);
for (int i = 0; i < out_contours[0].Length; i++) {
Cv2.Circle(_DetectImageMat, out_contours[0][i], 3, new Scalar(0, 0, 255), -1);
}
Cv2.Circle(_DetectImageMat, new Point(_ImageWidth / 2, _ImageHeight / 2), _SearchMin, new Scalar(255, 0, 0), 3);
Cv2.Circle(_DetectImageMat, new Point(_ImageWidth / 2, _ImageHeight / 2), _SearchMax, 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<IDrawObject> 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<double, double, double> 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<double> temp_dist = new List<double>();
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<double> lsPointRadius = new List<double>();
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;
// EdgeDetect Result Data
_SystemParameter.Serach_Max = SearchMax;
_SystemParameter.Serach_Min = SearchMin;
_SystemParameter.ReferenceX = ReferenceX;
_SystemParameter.ReferenceY = ReferenceY;
_SystemParameter.ReferenceTh = ReferenceTheta;
_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,
SelectedOption = SelectedOption,
CellType = CellType,
IsRepeatEdgeDetectMode = IsRepeatEdgeDetectMode,
CellRadiusOffset = CellRadiusOffset
};
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<string>()
});
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();
}
}
}