diff --git a/Configuration/AppSettings.cs b/Configuration/AppSettings.cs index 3515e09..1f5b3cb 100644 --- a/Configuration/AppSettings.cs +++ b/Configuration/AppSettings.cs @@ -17,6 +17,8 @@ public static readonly Rectangle ApertureCalculationRoi = new Rectangle(950, 1150, 128, 128); + public const int ApertureRoiMoveStep = 5; + public static Rectangle ApertureCalculationRoiRelativeToDisplay => new Rectangle( ApertureCalculationRoi.X - ApertureDisplayRoi.X, diff --git a/MainForm.cs b/MainForm.cs index 970c409..219b112 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -173,10 +173,13 @@ AddCaption(panel, "差(現在値 − 目標値)"); _apertureDifferenceValue = AddValueLabel(panel, "--"); + AddCaption(panel, "ROI位置微調整"); + panel.Controls.Add(CreateApertureRoiMovePanel()); + AddInstruction( panel, "現在値が目標値(±1.0)となるように\r\nレンズの開口を調整してください。\r\n\r\n" + - "赤枠: 計算ROI 128×128\r\n表示ROI: (860, 625), 1280×960"); + $"赤枠: 計算ROI 128×128\r\n表示ROI: (860, 625), 1280×960\r\nROI移動: {AppSettings.ApertureRoiMoveStep}px単位"); AddInstructionImage(panel, "LensApature.jpg"); page.Controls.Add(split); @@ -232,6 +235,47 @@ }); } + private TableLayoutPanel CreateApertureRoiMovePanel() + { + var panel = new TableLayoutPanel + { + ColumnCount = 3, + RowCount = 3, + Width = 150, + Height = 110, + Margin = new Padding(3, 4, 3, 12) + }; + + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 46F)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 46F)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 46F)); + panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F)); + panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F)); + panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 32F)); + + panel.Controls.Add(CreateApertureRoiMoveButton("↑", 0, -AppSettings.ApertureRoiMoveStep), 1, 0); + panel.Controls.Add(CreateApertureRoiMoveButton("←", -AppSettings.ApertureRoiMoveStep, 0), 0, 1); + panel.Controls.Add(CreateApertureRoiMoveButton("→", AppSettings.ApertureRoiMoveStep, 0), 2, 1); + panel.Controls.Add(CreateApertureRoiMoveButton("↓", 0, AppSettings.ApertureRoiMoveStep), 1, 2); + + return panel; + } + + private Button CreateApertureRoiMoveButton(string text, int deltaX, int deltaY) + { + var button = new Button + { + Text = text, + Width = 40, + Height = 28, + Font = new Font("Yu Gothic UI", 10F), + Margin = new Padding(3), + Tag = new Point(deltaX, deltaY) + }; + button.Click += ApertureRoiMoveButton_Click; + return button; + } + private static void AddCaption(Control parent, string text) { parent.Controls.Add(new Label @@ -406,6 +450,14 @@ _logger.Info("Focus maximum reset."); } + private void ApertureRoiMoveButton_Click(object sender, EventArgs e) + { + var button = (Button)sender; + var delta = (Point)button.Tag; + Rectangle roi = _processor.MoveApertureCalculationRoi(delta.X, delta.Y); + _logger.Info($"Aperture ROI moved to ({roi.X}, {roi.Y})."); + } + private void UiTimer_Tick(object sender, EventArgs e) { _cameraStatusLabel.Text = "Camera: " + _camera.StatusText; diff --git a/Processing/LensAdjustmentProcessor.cs b/Processing/LensAdjustmentProcessor.cs index d75df9d..468d4b4 100644 --- a/Processing/LensAdjustmentProcessor.cs +++ b/Processing/LensAdjustmentProcessor.cs @@ -12,7 +12,9 @@ { private int _mode = (int)AdjustmentMode.Focus; private readonly object _focusMaxSync = new object(); + private readonly object _apertureRoiSync = new object(); private double _focusMaximum; + private Rectangle _apertureCalculationRoi = AppSettings.ApertureCalculationRoi; public AdjustmentMode Mode => (AdjustmentMode)Volatile.Read(ref _mode); @@ -33,6 +35,28 @@ } } + public Rectangle MoveApertureCalculationRoi(int deltaX, int deltaY) + { + lock (_apertureRoiSync) + { + Rectangle displayRoi = AppSettings.ApertureDisplayRoi; + int x = Math.Max( + displayRoi.X, + Math.Min(_apertureCalculationRoi.X + deltaX, displayRoi.Right - _apertureCalculationRoi.Width)); + int y = Math.Max( + displayRoi.Y, + Math.Min(_apertureCalculationRoi.Y + deltaY, displayRoi.Bottom - _apertureCalculationRoi.Height)); + + _apertureCalculationRoi = new Rectangle( + x, + y, + _apertureCalculationRoi.Width, + _apertureCalculationRoi.Height); + + return _apertureCalculationRoi; + } + } + public FrameAnalysisResult Process(IFrameQueueBuffer frame) { if (frame == null) throw new ArgumentNullException(nameof(frame)); @@ -93,7 +117,12 @@ Bitmap display = Clone24(fullFrame, AppSettings.ApertureDisplayRoi); try { - Rectangle relativeCalc = AppSettings.ApertureCalculationRoiRelativeToDisplay; + Rectangle calculationRoi = GetApertureCalculationRoi(); + Rectangle relativeCalc = new Rectangle( + calculationRoi.X - AppSettings.ApertureDisplayRoi.X, + calculationRoi.Y - AppSettings.ApertureDisplayRoi.Y, + calculationRoi.Width, + calculationRoi.Height); using (Bitmap calculation = Clone24(display, relativeCalc)) { double mean = ApertureAnalyzer.CalculateMeanLuminance(calculation); @@ -124,6 +153,14 @@ } } + private Rectangle GetApertureCalculationRoi() + { + lock (_apertureRoiSync) + { + return _apertureCalculationRoi; + } + } + private static Bitmap Clone24(Bitmap source, Rectangle roi) { Rectangle bounds = new Rectangle(0, 0, source.Width, source.Height);