- 오토런 시작 시 RCC 패턴 폴더 변경 감지 → B2506 ON, PLC ACK(B2409) 수신 시 OFF - 서브 패턴 1~10, 패턴 목록에 서브 썸네일 표시(행 내 좌우 스크롤) - 서브 패턴 등록 직후 활성화 OFF - 패턴 파일이 다른 프로그램에서 열려 있으면 삭제하지 않고 안내 - 현장 소스 반영: Train ROI 슬라이더, KS 조명 밝기 저장/적용, 조명 ID 분리, 스캔 후 카메라 라이브 재시작, 레시피 21 RCC NG 우회, 오토런 상태 판단
455 lines
18 KiB
C#
455 lines
18 KiB
C#
/*
|
|
* Copyright (c) 2025 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using Aurora.Api;
|
|
using Aurora.Api.DataType;
|
|
using Aurora.View;
|
|
using VisionLight;
|
|
using MilCommon;
|
|
using VisionCommon;
|
|
using Hermes;
|
|
using MilPattern;
|
|
using VisionCommonUI;
|
|
using VisionCommonUI.Resources;
|
|
|
|
namespace MilUI {
|
|
public class PatternMatchingSettingViewModel : NotifyPropertyChangedBase, IGraEventSubscriber {
|
|
private Logger _logger = new Logger("PatternMatchingSettingVM");
|
|
|
|
public ICommand CMD_VisibleChanged { get; }
|
|
public ICommand CMD_Copy { get; }
|
|
public ICommand CMD_Create { get; }
|
|
public ICommand CMD_Save { get; }
|
|
public ICommand CMD_Cancel { get; }
|
|
public ICommand CMD_Delete { get; }
|
|
public ICommand CMD_SetLight { get; }
|
|
public ICommand CMD_SetPreProc { get; }
|
|
public ICommand CMD_SetTrainROI { get; }
|
|
public ICommand CMD_TrainPattern { get; }
|
|
public ICommand CMD_SetMask { get; }
|
|
public ICommand CMD_SetFindROI { get; }
|
|
public ICommand CMD_FindPattern { get; }
|
|
public ICommand CMD_SyncTrainOrigin { get; }
|
|
|
|
public bool IsSubPattern { get; set; }
|
|
|
|
private bool _isPatternRegistered;
|
|
public bool IsPatternRegistered { get => _isPatternRegistered; set => SetProperty(ref _isPatternRegistered, value); }
|
|
|
|
private bool _isSubPatternRegistered;
|
|
public bool IsSubPatternRegistered { get => _isSubPatternRegistered; set => SetProperty(ref _isSubPatternRegistered, value); }
|
|
|
|
private bool _isSubPatternNotRegistered;
|
|
public bool IsSubPatternNotRegistered { get => _isSubPatternNotRegistered; set => SetProperty(ref _isSubPatternNotRegistered, value); }
|
|
|
|
private PatternInfo _patternInfo;
|
|
public PatternInfo PatternInfo { get => _patternInfo; set => SetProperty(ref _patternInfo, value); }
|
|
|
|
private PatternMatchingTrainParam _trainParam;
|
|
public PatternMatchingTrainParam TrainParam { get => _trainParam; set => SetProperty(ref _trainParam, value); }
|
|
|
|
private PatternMatchingRunParam _runParam;
|
|
public PatternMatchingRunParam RunParam { get => _runParam; set => SetProperty(ref _runParam, value); }
|
|
|
|
private double _trainRoiSize = 25;
|
|
public double TrainRoiSize {
|
|
get => _trainRoiSize;
|
|
set {
|
|
if (SetProperty(ref _trainRoiSize, value)) {
|
|
if (RunParam?.PmParamExt != null) {
|
|
RunParam.PmParamExt.TrainRoiSize = value;
|
|
}
|
|
if (!_isUpdatingFromDisplay) {
|
|
if (_cameraDisplay != null && _cameraDisplay.HasTrainOrigin()) {
|
|
_cameraDisplay.UpdateRadiusOfTrainOrigin(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _isUpdatingFromDisplay = false;
|
|
|
|
private IEnumerable<int> _fixturePatterns;
|
|
public IEnumerable<int> FixturePatterns { get => _fixturePatterns; set => SetProperty(ref _fixturePatterns, value); }
|
|
|
|
public IEnumerable<eMilPatSpeed> SpeedItems { get; } = Enum.GetValues(typeof(eMilPatSpeed)).Cast<eMilPatSpeed>();
|
|
public IEnumerable<eMilAccuracy> AccuracyItems { get; } = Enum.GetValues(typeof(eMilAccuracy)).Cast<eMilAccuracy>();
|
|
|
|
private PatternAgentBase _patternAgent;
|
|
private CameraDisplay _cameraDisplay;
|
|
private FovInfo _fovInfo;
|
|
private Window _childWindow = null;
|
|
|
|
public PatternMatchingSettingViewModel(
|
|
PatternAgentBase patternAgent, PatternInfo patternInfo, CameraDisplay milCameraDisplay, FovInfo fovInfo) {
|
|
_patternAgent = patternAgent;
|
|
_patternInfo = patternInfo;
|
|
_cameraDisplay = milCameraDisplay;
|
|
_fovInfo = fovInfo;
|
|
IsSubPattern = PatternConstants.IsSubPattern(_patternInfo.GetPatternIndex());
|
|
|
|
CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
|
|
CMD_Copy = new DelegateCommand(Copy);
|
|
CMD_Create = new DelegateCommand(Create);
|
|
CMD_Save = new DelegateCommand(Save);
|
|
CMD_Cancel = new DelegateCommand(Cancel);
|
|
CMD_Delete = new DelegateCommand(Delete);
|
|
|
|
CMD_SetLight = new DelegateCommand(SetLight);
|
|
CMD_SetPreProc = new DelegateCommand(SetPreProc);
|
|
CMD_SetTrainROI = new DelegateCommand(SetTrainROI);
|
|
CMD_TrainPattern = new DelegateCommand(TrainPattern);
|
|
CMD_SetMask = new DelegateCommand(SetMask);
|
|
CMD_SetFindROI = new DelegateCommand(SetFindROI);
|
|
CMD_FindPattern = new DelegateCommand(FindPattern);
|
|
CMD_SyncTrainOrigin = new DelegateCommand(SyncTrainOrigin);
|
|
|
|
InitRegistered();
|
|
InitRunParam();
|
|
InitFixturePatterns();
|
|
UpdateControlButtons(IsPatternRegistered);
|
|
_cameraDisplay.SetGraEventSubscriber(_patternInfo, this);
|
|
}
|
|
|
|
public void InitRegistered() {
|
|
IsPatternRegistered = _patternAgent.IsPatternExist(_patternInfo.GetPatternIndex());
|
|
}
|
|
|
|
public void InitRunParam() {
|
|
if (_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
|
RunParam = _patternAgent.GetRunParam(_patternInfo) as PatternMatchingRunParam;
|
|
}
|
|
else {
|
|
RunParam = new PatternMatchingRunParam();
|
|
}
|
|
if (RunParam?.PmParamExt != null && RunParam.PmParamExt.TrainRoiSize > 0) {
|
|
_trainRoiSize = RunParam.PmParamExt.TrainRoiSize;
|
|
NotifyPropertyChanged(nameof(TrainRoiSize));
|
|
}
|
|
}
|
|
|
|
public void InitFixturePatterns() {
|
|
FixturePatterns = _patternAgent.GetFixturePatternIndexListForFov(_patternInfo);
|
|
}
|
|
|
|
private void UpdateControlButtons(bool isPatternRegistered) {
|
|
IsPatternRegistered = isPatternRegistered;
|
|
IsSubPatternRegistered = IsSubPattern && isPatternRegistered;
|
|
IsSubPatternNotRegistered = IsSubPattern && !isPatternRegistered;
|
|
}
|
|
|
|
private void VisibleChanged(object obj) {
|
|
bool visible = (bool)obj;
|
|
if (visible == false) {
|
|
CloseChildWindow();
|
|
ClosingWindow();
|
|
}
|
|
}
|
|
|
|
private void Copy(object obj) {
|
|
var result = MessageBoxUtil.ShowMessageBoxQuestion(StrTokens.MSG_Q_CopyPatternZero);
|
|
if (result == MessageBoxResult.Yes) {
|
|
var mainPatternInfo = _patternAgent.GetMainPatternInfo(_patternInfo.GetPatternIndex());
|
|
if (E1.OK == _patternAgent.CopyPattern(mainPatternInfo.GetPatternIndex(), _patternInfo.GetPatternIndex())) {
|
|
DeactivateRegisteredSubPattern();
|
|
InitRunParam();
|
|
InitFixturePatterns();
|
|
UpdateControlButtons(true);
|
|
MessageBoxUtil.ShowMessageBoxOk(StrTokens.MSG_O_CopyCompleted);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Create(object obj) {
|
|
if (!_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
|
if (E1.OK == _patternAgent.Create(_patternInfo) &&
|
|
E1.OK == _patternAgent.Save(_patternInfo)) {
|
|
DeactivateRegisteredSubPattern();
|
|
InitRunParam();
|
|
InitFixturePatterns();
|
|
UpdateControlButtons(true);
|
|
MessageBoxUtil.ShowMessageBoxOk(StrTokens.MSG_O_RegisterCompleted);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Save(object obj) {
|
|
if (_cameraDisplay.HasFindRoi()) {
|
|
RunParam.SetFindROI(_cameraDisplay.GetFindRoi().Clone() as ROI);
|
|
}
|
|
if (RunParam?.PmParamExt != null) {
|
|
RunParam.PmParamExt.TrainRoiSize = TrainRoiSize;
|
|
}
|
|
_patternAgent.SetRunParam(_patternInfo, RunParam);
|
|
_patternAgent.Save(_patternInfo);
|
|
MessageBoxUtil.ShowMessageBoxOk(StrTokens.MSG_O_SaveCompleted);
|
|
}
|
|
|
|
private void Cancel(object obj) {
|
|
CloseChildWindow();
|
|
ClosingWindow();
|
|
CloseWindow(obj);
|
|
}
|
|
|
|
private void Delete(object obj) {
|
|
var result = MessageBoxUtil.ShowMessageBoxQuestion(StrTokens.MSG_Q_Delete);
|
|
if (result == MessageBoxResult.Yes) {
|
|
if (_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
|
if (_patternAgent.IsPatternFileLocked(_patternInfo, out string lockedFilePath)) {
|
|
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(lockedFilePath));
|
|
return;
|
|
}
|
|
if (E1.OK == _patternAgent.Remove(_patternInfo)) {
|
|
UpdateControlButtons(false);
|
|
}
|
|
else {
|
|
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(string.Empty));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sub pattern is registered as OFF (IsActivated = false). The operator turns it ON after checking.
|
|
private void DeactivateRegisteredSubPattern() {
|
|
if (!IsSubPattern) {
|
|
return;
|
|
}
|
|
|
|
_patternInfo.IsActivated = false;
|
|
|
|
var registeredPatternInfo = _patternAgent.GetPatternInfo(_patternInfo.GetPatternIndex());
|
|
if (registeredPatternInfo != null) {
|
|
registeredPatternInfo.IsActivated = false;
|
|
_patternAgent.Save(registeredPatternInfo);
|
|
}
|
|
}
|
|
|
|
private void ClosingWindow() {
|
|
_cameraDisplay.ClearTrainGraphics();
|
|
_cameraDisplay.ClearFindGraphics();
|
|
}
|
|
|
|
private void CloseChildWindow() {
|
|
if (_childWindow != null) {
|
|
_childWindow.Close();
|
|
}
|
|
}
|
|
|
|
private void CloseWindow(object obj) {
|
|
var window = obj as Window;
|
|
if (window != null) {
|
|
window.Close();
|
|
}
|
|
}
|
|
|
|
private void SetLight(object obj) {
|
|
PatternLightWindowManager.ShowLightSettingWindow(_fovInfo, _patternInfo);
|
|
}
|
|
|
|
private void SetPreProc(object obj) {
|
|
if (_childWindow == null) {
|
|
_childWindow = new PreProcessingWindow(_patternInfo, _cameraDisplay);
|
|
(_childWindow as IPatternSettingWindow).ResetPosition();
|
|
_childWindow.Closed += OnWindowClosed;
|
|
_childWindow.Owner = Application.Current.MainWindow;
|
|
_childWindow.Show();
|
|
}
|
|
else {
|
|
ResetWindow();
|
|
}
|
|
}
|
|
|
|
private void SetTrainROI(object obj) {
|
|
_cameraDisplay.SetPatternInfo(_patternInfo);
|
|
var milImage = _cameraDisplay.GetImage();
|
|
if (milImage != 0) {
|
|
var curPattern = _patternAgent.GetPattern(_patternInfo) as IPatternTrain;
|
|
TrainParam = curPattern.GetTrainParam() as PatternMatchingTrainParam;
|
|
|
|
_cameraDisplay.ClearTrainGraphics();
|
|
var imageCenter = MilEnvironment.GetImageCenter(milImage);
|
|
if (ROI.IsNullOrEmpty(TrainParam.TrainRoi) || TrainParam.TrainOrigin is null) {
|
|
_cameraDisplay.AddTrainRoi(imageCenter);
|
|
_cameraDisplay.AddTrainOrigin(new Cross(imageCenter, TrainRoiSize));
|
|
}
|
|
else {
|
|
if (TrainParam.TrainOrigin.Length <= 0) {
|
|
TrainParam.TrainOrigin.Length = TrainRoiSize;
|
|
}
|
|
else {
|
|
TrainRoiSize = TrainParam.TrainOrigin.Length;
|
|
}
|
|
_cameraDisplay.AddTrainRoi(TrainParam.TrainRoi);
|
|
_cameraDisplay.AddTrainOrigin(TrainParam.TrainOrigin);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void TrainPattern(object obj) {
|
|
if (_cameraDisplay != null) {
|
|
var trainRoi = _cameraDisplay.GetTrainRoi();
|
|
if (ROI.IsNullOrEmpty(trainRoi)) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_TrainRoiNotSet);
|
|
return;
|
|
}
|
|
var trainOrigin = _cameraDisplay.GetTrainOrigin();
|
|
if (!IsValidTrainOrigin(trainOrigin)) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_InvalidTrainOrigin);
|
|
return;
|
|
}
|
|
|
|
var result = MessageBoxUtil.ShowMessageBoxQuestion(StrTokens.MSG_Q_ContinuToTrainPattern);
|
|
if (result == MessageBoxResult.Yes) {
|
|
var image = _cameraDisplay.GetImage();
|
|
|
|
_cameraDisplay.ClearTrainGraphics();
|
|
_patternAgent.Train(
|
|
_patternInfo,
|
|
new PatternMatchingTrainParam() {
|
|
TrainImage = image,
|
|
TrainRoi = trainRoi.Clone() as ROI,
|
|
TrainOrigin = trainOrigin.Clone() as Cross
|
|
});
|
|
|
|
MessageBoxUtil.ShowMessageBoxOk(StrTokens.MSG_O_TrainCompleted);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IsValidTrainOrigin(Cross trainOrigin) {
|
|
var milImage = _cameraDisplay.GetImage();
|
|
if (milImage != 0) {
|
|
var imageSize = MilEnvironment.GetImageSize(milImage);
|
|
var findRoi = _cameraDisplay.GetFindRoi();
|
|
|
|
if (ROI.IsNullOrEmpty(findRoi)) {
|
|
findRoi = GetFindROIFromRunParam(imageSize, RunParam);
|
|
}
|
|
if (trainOrigin.Origin.X < findRoi.Left || trainOrigin.Origin.Y < findRoi.Top ||
|
|
trainOrigin.Origin.X > findRoi.Right || trainOrigin.Origin.Y > findRoi.Bottom) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void SetMask(object obj) {
|
|
if (_childWindow == null) {
|
|
var curPattern = _patternAgent.GetPattern(_patternInfo) as IPatternTrain;
|
|
if (curPattern != null && curPattern.IsTrained()) {
|
|
_childWindow = new ImageMaskViewWindow(_patternAgent, _patternInfo);
|
|
(_childWindow as IPatternSettingWindow).ResetPosition();
|
|
_childWindow.Closed += OnWindowClosed;
|
|
_childWindow.Owner = Application.Current.MainWindow;
|
|
_childWindow.Show();
|
|
}
|
|
else {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_PatternNotTrained);
|
|
}
|
|
}
|
|
else {
|
|
ResetWindow();
|
|
}
|
|
}
|
|
|
|
private void ResetWindow() {
|
|
if (_childWindow.WindowState == WindowState.Minimized) {
|
|
_childWindow.WindowState = WindowState.Normal;
|
|
}
|
|
|
|
(_childWindow as IPatternSettingWindow).ResetPosition();
|
|
}
|
|
|
|
private void OnWindowClosed(object sender, EventArgs e) {
|
|
_childWindow = null;
|
|
}
|
|
|
|
private void SetFindROI(object obj) {
|
|
var milImage = _cameraDisplay.GetImage();
|
|
if (milImage != 0) {
|
|
var imageSize = MilEnvironment.GetImageSize(milImage);
|
|
var findRoi = GetFindROIFromRunParam(imageSize, RunParam);
|
|
_cameraDisplay.AddFindRoi(findRoi);
|
|
}
|
|
}
|
|
|
|
private ROI GetFindROIFromRunParam(ImageSize imageSize, PatternMatchingRunParam runParam) {
|
|
if (runParam.IsValidFindRoi(imageSize)) {
|
|
return runParam.GetFindRoi();
|
|
}
|
|
|
|
return RoiUtil.GetDefaultFindRoi(imageSize);
|
|
}
|
|
|
|
private void FindPattern(object obj) {
|
|
if (!_patternInfo.IsActivated) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_PatternNotActivated);
|
|
return;
|
|
}
|
|
|
|
if (_cameraDisplay != null) {
|
|
var image = _cameraDisplay.GetImage();
|
|
if (image == null) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_ImageNotReady);
|
|
return;
|
|
}
|
|
if (_cameraDisplay.HasFindRoi()) {
|
|
RunParam.SetFindROI(_cameraDisplay.GetFindRoi().Clone() as ROI);
|
|
}
|
|
|
|
_cameraDisplay.ClearTrainGraphics();
|
|
_cameraDisplay.ClearFindGraphics();
|
|
_cameraDisplay.ClearMeasureGraphics();
|
|
|
|
_patternAgent.SetRunParam(_patternInfo, RunParam);
|
|
var patternResult = _patternAgent.Find(_patternInfo, image);
|
|
_patternAgent.Draw(_patternInfo, patternResult, _cameraDisplay);
|
|
|
|
if (patternResult.Status == eFoundStatus.NotFound) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_PatternNotFound);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SyncTrainOrigin(object obj) {
|
|
if (_childWindow == null) {
|
|
if (_patternAgent.HasSubPattern(_patternInfo)) {
|
|
_childWindow = new TrainOriginSyncWindow(_patternAgent, _patternInfo, _cameraDisplay);
|
|
(_childWindow as IPatternSettingWindow).ResetPosition();
|
|
_childWindow.Closed += OnWindowClosed;
|
|
_childWindow.Owner = Application.Current.MainWindow;
|
|
_childWindow.Show();
|
|
}
|
|
else {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_NoSubPatterns);
|
|
}
|
|
}
|
|
else {
|
|
ResetWindow();
|
|
}
|
|
}
|
|
|
|
public void UpdateAngleOfRoi(eGraRoiType graRoiType, object param) {
|
|
}
|
|
|
|
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
|
if (graRoiType == eGraRoiType.TrainOrigin) {
|
|
_isUpdatingFromDisplay = true;
|
|
try {
|
|
TrainRoiSize = Math.Min(500, Math.Max(1, Math.Round(radius, 1)));
|
|
}
|
|
finally {
|
|
_isUpdatingFromDisplay = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|