|
@@ -0,0 +1,403 @@
|
|
|
+
|
|
|
+using OTSCLRINTERFACE;
|
|
|
+using OTSCommon.DBOperate.Model;
|
|
|
+using OTSDataType;
|
|
|
+using OTSMeasureApp._0_OTSModel.OTSDataType;
|
|
|
+using OTSModelSharp;
|
|
|
+using OTSModelSharp.ServiceCenter;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics.Contracts;
|
|
|
+using System.Drawing;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using static OTSDataType.otsdataconst;
|
|
|
+
|
|
|
+namespace OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow
|
|
|
+{
|
|
|
+ internal class CBrightnessContrastAdjust
|
|
|
+ {
|
|
|
+
|
|
|
+ protected static NLog.Logger log;
|
|
|
+
|
|
|
+
|
|
|
+ protected CMeasure m_pMsrThread;
|
|
|
+
|
|
|
+ double curbrightness = 0, curcontrast = 0;
|
|
|
+
|
|
|
+ protected ISemController m_SemHardwareMgr;
|
|
|
+ protected IScanController m_ScanHardwareMgr;
|
|
|
+ CBrightnessContrastRegulateParam m_BrightnessContrastRegulateParam = new CBrightnessContrastRegulateParam();
|
|
|
+ int imgwidth = 0;
|
|
|
+ int imgheight = 0;
|
|
|
+ internal CBrightnessContrastRegulateParam BrightnessContrastRegulationParam { get => m_BrightnessContrastRegulateParam; set => m_BrightnessContrastRegulateParam = value; }
|
|
|
+ private DateTime periodStart = DateTime.Now;
|
|
|
+ public void SetPeriodStart(DateTime a_periodStart)
|
|
|
+ {
|
|
|
+ periodStart = a_periodStart;
|
|
|
+ }
|
|
|
+ public DateTime GetPeriodStart()
|
|
|
+ {
|
|
|
+ return periodStart;
|
|
|
+ }
|
|
|
+ public bool checkPeriodTime()
|
|
|
+ {
|
|
|
+ if(!m_BrightnessContrastRegulateParam.toRun)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (m_BrightnessContrastRegulateParam.autoRegulateType == AutoRegulateType.EveryPeriod)
|
|
|
+ {
|
|
|
+ if ((DateTime.Now - periodStart).TotalMinutes > m_BrightnessContrastRegulateParam.period)
|
|
|
+ {
|
|
|
+ periodStart = DateTime.Now;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (m_BrightnessContrastRegulateParam.autoRegulateType == AutoRegulateType.EverySample)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ public bool CheckIsSampleAutoRegulate()
|
|
|
+ {
|
|
|
+ if (!m_BrightnessContrastRegulateParam.toRun)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (m_BrightnessContrastRegulateParam.autoRegulateType == AutoRegulateType.EverySample)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public CBrightnessContrastAdjust(CMeasure a_msrThread)
|
|
|
+ {
|
|
|
+ m_pMsrThread = a_msrThread;
|
|
|
+
|
|
|
+ log = NLog.LogManager.GetCurrentClassLogger();
|
|
|
+
|
|
|
+ imgwidth = m_pMsrThread.m_pMeasureParam.GetDefaultParam().GetImageScanParam().GetImageResolutionSize().cx/2;
|
|
|
+ imgheight = m_pMsrThread.m_pMeasureParam.GetDefaultParam().GetImageScanParam().GetImageResolutionSize().cy/2;
|
|
|
+
|
|
|
+ m_BrightnessContrastRegulateParam = a_msrThread.m_pMeasureParam.GetDefaultParam().BrightnessContrastRegulationParam;
|
|
|
+
|
|
|
+ m_SemHardwareMgr = SemController.GetSEMController();
|
|
|
+ m_ScanHardwareMgr = ScanController.GetScanController();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ private class SEMStateObject
|
|
|
+ {
|
|
|
+ private PointF pos;
|
|
|
+ private double workingDistance;
|
|
|
+
|
|
|
+ private double magnification;
|
|
|
+ public PointF Pos { get => pos; set => pos = value; }
|
|
|
+ public double WorkingDistance { get => workingDistance; set => workingDistance = value; }
|
|
|
+
|
|
|
+ public double Magnification { get => magnification; set => magnification = value; }
|
|
|
+ public double brightness { get; set; }
|
|
|
+ public double contrast { get; set; }
|
|
|
+ public Size ScanImagesize { get; set; }
|
|
|
+
|
|
|
+ }
|
|
|
+ private class AutoResetSEMControl : IDisposable
|
|
|
+ {
|
|
|
+ CBrightnessContrastAdjust sm;
|
|
|
+ private SEMStateObject semState = null;
|
|
|
+ public AutoResetSEMControl(CBrightnessContrastAdjust s)
|
|
|
+ {
|
|
|
+ sm = s;
|
|
|
+ }
|
|
|
+
|
|
|
+ public SEMStateObject SemState
|
|
|
+ {
|
|
|
+ get => semState;
|
|
|
+ set => semState = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Dispose()
|
|
|
+ {
|
|
|
+ if (semState != null)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ sm.m_SemHardwareMgr.SetMagnification(semState.Magnification);
|
|
|
+ Thread.Sleep(100);
|
|
|
+ sm.MoveSEMToPoint(semState.Pos);
|
|
|
+ Thread.Sleep(100);
|
|
|
+ sm.m_SemHardwareMgr.SetWorkingDistance(semState.WorkingDistance);
|
|
|
+
|
|
|
+ sm.m_ScanHardwareMgr.SetImageSize(semState.ScanImagesize.Width,semState.ScanImagesize.Height);
|
|
|
+ }
|
|
|
+ log.Warn("Set SEM Exteral Off!");
|
|
|
+ sm.m_SemHardwareMgr.SetScanExternal(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public bool MoveSEMToPoint(System.Drawing.PointF a_poi)
|
|
|
+ {
|
|
|
+ // get SEM controller
|
|
|
+ var pSEMController = m_SemHardwareMgr;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ PointF a_SEMpt = new Point();
|
|
|
+
|
|
|
+ CSEMStageData a_pCSEMStageData = m_pMsrThread.m_pMeasureParam.GetDefaultParam().GetStageDataParam();
|
|
|
+ int hardWareDelay = a_pCSEMStageData.GetHardWareDelay();
|
|
|
+
|
|
|
+
|
|
|
+ if (!a_pCSEMStageData.ConvertOTSToSEMCoord(a_poi, ref a_SEMpt))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //log.Info("Begin to move SEM stage to OTScoord:" + a_poi.X + "," + a_poi.Y);
|
|
|
+
|
|
|
+ log.Info("Begin to move SEM stage to " + a_SEMpt.X + "," + a_SEMpt.Y);
|
|
|
+
|
|
|
+ // move SEM to the position (rotation 0)
|
|
|
+ if (!pSEMController.MoveSEMToPoint(a_SEMpt.X, a_SEMpt.Y))
|
|
|
+ {
|
|
|
+ log.Error("MoveSEMToPoint: failed to call MoveSEMToPoint method.");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hardWareDelay > 0)
|
|
|
+ {
|
|
|
+ Thread.Sleep(hardWareDelay);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ public void DoBrightnessContrastAdjust()
|
|
|
+ {
|
|
|
+ using (AutoResetSEMControl autoReset = new AutoResetSEMControl(this))
|
|
|
+ {
|
|
|
+ log.Warn("begin to do auto brightness and contrast adjust.");
|
|
|
+ //----------memorize the state of sem
|
|
|
+ var semstate = new SEMStateObject();
|
|
|
+
|
|
|
+ double dMagnification = 0;
|
|
|
+ m_SemHardwareMgr.GetMagnification(ref dMagnification);
|
|
|
+ double wd = 0;
|
|
|
+ m_SemHardwareMgr.GetWorkingDistance(ref wd);
|
|
|
+ ISemController sem = m_SemHardwareMgr;
|
|
|
+ double posX = 0, posY = 0, posR = 0;
|
|
|
+ sem.GetSemPositionXY(ref posX, ref posY, ref posR);
|
|
|
+
|
|
|
+ CSEMStageData a_pCSEMStageData = m_pMsrThread.m_pMeasureParam.GetDefaultParam().GetStageDataParam();
|
|
|
+
|
|
|
+ Point pos = new Point((int)posX, (int)posY);
|
|
|
+ PointF otsPos = new Point(0, 0);
|
|
|
+
|
|
|
+ if (!a_pCSEMStageData.ConvertSEMToOTSCoord(pos, ref otsPos))
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ semstate.Pos = otsPos;
|
|
|
+ semstate.Magnification = dMagnification;
|
|
|
+ semstate.WorkingDistance = wd;
|
|
|
+ CSize size = m_pMsrThread.m_pMeasureParam.GetDefaultParam().GetImageScanParam().GetImageResolutionSize();
|
|
|
+ semstate.ScanImagesize =new Size(size.cx, size.cy );
|
|
|
+
|
|
|
+ autoReset.SemState =semstate;
|
|
|
+
|
|
|
+
|
|
|
+ //-------------------------------------
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ double dMag = m_BrightnessContrastRegulateParam.mag;
|
|
|
+ // get SEM controller to set magnification and working distance
|
|
|
+ if (!m_SemHardwareMgr.SetMagnification(dMag))
|
|
|
+ {
|
|
|
+ log.Error("fail to set magnification.");
|
|
|
+
|
|
|
+ }
|
|
|
+ InitAcquireBSEParam();
|
|
|
+ // move sem to std position
|
|
|
+ if (!MoveSEMToPoint(m_BrightnessContrastRegulateParam.stdMaterialOTSPos))
|
|
|
+ {
|
|
|
+ log.Error(" failed to move SEM to the field centre point.");
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_SemHardwareMgr.SetSemContrast(m_BrightnessContrastRegulateParam.initialContrast);
|
|
|
+ m_SemHardwareMgr.SetSemBrightness(m_BrightnessContrastRegulateParam.initialBrightness);
|
|
|
+ CBSEImgClr pBSEIamge = m_ScanHardwareMgr.AcquireBSEImage();
|
|
|
+ if (pBSEIamge == null)
|
|
|
+ {
|
|
|
+
|
|
|
+ log.Error("failed to acquire a BSE image.");
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int bright = 0, dark = 0;
|
|
|
+ ProcessBSEImageToGetTheTwoGrayValue(pBSEIamge, ref bright, ref dark);
|
|
|
+ var starttime = DateTime.Now;
|
|
|
+
|
|
|
+ var desiredark = m_BrightnessContrastRegulateParam.darkphaseGrayvalue;
|
|
|
+ var desirebright = m_BrightnessContrastRegulateParam.brightphaseGrayvalue;
|
|
|
+
|
|
|
+ SortedDictionary<double, SEMStateObject> BCstatedic =new SortedDictionary<double, SEMStateObject>();
|
|
|
+
|
|
|
+ while (Math.Abs( dark-desiredark)>3 || Math.Abs(bright-desirebright)>3)
|
|
|
+ {
|
|
|
+
|
|
|
+ if (m_pMsrThread.IsMeasureStopped())
|
|
|
+ {// measure stopped
|
|
|
+ log.Trace("measure thread is stopped.");
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ double curbrightness = 0, curcontrast = 0;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var error1 = desirebright - bright;
|
|
|
+ var error2 = desiredark - dark;
|
|
|
+ var varerror = Math.Pow(error1, 2) + Math.Pow(error2, 2);
|
|
|
+ SEMStateObject BcsemState = new SEMStateObject();
|
|
|
+ m_SemHardwareMgr.GetSemBrightness(ref curbrightness);
|
|
|
+ m_SemHardwareMgr.GetSemContrast(ref curcontrast);
|
|
|
+ BcsemState.brightness = curbrightness;
|
|
|
+ BcsemState.contrast = curcontrast;
|
|
|
+ if(!BCstatedic.ContainsKey(varerror))
|
|
|
+ {
|
|
|
+ BCstatedic.Add(varerror, BcsemState);
|
|
|
+ }
|
|
|
+ if((DateTime.Now-starttime).TotalSeconds>20)
|
|
|
+ {
|
|
|
+ log.Warn("Auto BC time out, stop the auto BC!");
|
|
|
+
|
|
|
+ if (BCstatedic.Count > 0)
|
|
|
+ {
|
|
|
+ var minerror = BCstatedic.Keys.Min();
|
|
|
+ var minstate = BCstatedic[minerror];
|
|
|
+ m_SemHardwareMgr.SetSemBrightness(minstate.brightness);
|
|
|
+ m_SemHardwareMgr.SetSemContrast(minstate.contrast);
|
|
|
+ log.Warn("Auto BC set brightness and contrast to:" + minstate.brightness + " " + minstate.contrast);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ RegulateBrightnessAndContrast(bright, desirebright, dark, desiredark,curbrightness,curcontrast);
|
|
|
+
|
|
|
+ log.Info("two gray:" + bright.ToString() +" "+ dark.ToString());
|
|
|
+ Thread.Sleep(500);
|
|
|
+
|
|
|
+ // take BSE image for the fields
|
|
|
+ pBSEIamge = m_ScanHardwareMgr.AcquireBSEImage();
|
|
|
+
|
|
|
+ if (pBSEIamge == null)
|
|
|
+ {
|
|
|
+ log.Error(" failed to acquire a BSE image.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ ProcessBSEImageToGetTheTwoGrayValue(pBSEIamge, ref bright, ref dark);
|
|
|
+
|
|
|
+ }
|
|
|
+ m_SemHardwareMgr.GetSemContrast(ref m_BrightnessContrastRegulateParam.initialContrast);
|
|
|
+ m_SemHardwareMgr.GetSemBrightness(ref m_BrightnessContrastRegulateParam.initialBrightness);
|
|
|
+ log.Warn("Auto BC done!");
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ProcessBSEImageToGetTheTwoGrayValue(CBSEImgClr pBSEIamge, ref int bright, ref int dark)
|
|
|
+ {
|
|
|
+ CImageHandler imageHandler = new CImageHandler();
|
|
|
+ imageHandler.CalculateBrightnessDarkGrayByOtsu(pBSEIamge, ref bright, ref dark);
|
|
|
+ }
|
|
|
+ public void GetCurrentTwoProminentGray(ref int dark, ref int bright)
|
|
|
+ {
|
|
|
+ InitAcquireBSEParam();
|
|
|
+ var pBSEIamge = m_ScanHardwareMgr.AcquireBSEImage();
|
|
|
+ CImageHandler imageHandler = new CImageHandler();
|
|
|
+ imageHandler.CalculateBrightnessDarkGrayByOtsu(pBSEIamge, ref bright, ref dark);
|
|
|
+
|
|
|
+ }
|
|
|
+ public void GetCurrentBrightnessAndContrast(ref double bright, ref double contrast)
|
|
|
+ {
|
|
|
+
|
|
|
+ m_SemHardwareMgr.GetSemBrightness(ref bright);
|
|
|
+ m_SemHardwareMgr.GetSemContrast(ref contrast);
|
|
|
+ }
|
|
|
+ public void WriteBrightnessAndContrast(ref double bright, ref double contrast)
|
|
|
+ {
|
|
|
+
|
|
|
+ m_SemHardwareMgr.SetSemContrast(contrast);
|
|
|
+ m_SemHardwareMgr.SetSemBrightness(bright);
|
|
|
+ }
|
|
|
+ void RegulateBrightnessAndContrast(double bri, double desirebri, double dark, double desiredark,double curbrightness,double curcontrast)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ var amplifierScope =6;//the scope that sem brightness and contrast can be adjusted
|
|
|
+
|
|
|
+ var error1 = desirebri - bri;
|
|
|
+ var error2 = desiredark - dark;
|
|
|
+
|
|
|
+ var error = error1 + error2;
|
|
|
+ double brightness = curbrightness + (error/255)* amplifierScope;
|
|
|
+ if (bri - dark > 10)
|
|
|
+ {
|
|
|
+ double expectcontrast = (desirebri - desiredark) / desirebri;
|
|
|
+ double currentcontrast = (bri - dark) / bri;
|
|
|
+ double gain= (expectcontrast-currentcontrast)/expectcontrast* amplifierScope;
|
|
|
+ double contrast = curcontrast +gain;
|
|
|
+ m_SemHardwareMgr.SetSemContrast(contrast);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ m_SemHardwareMgr.SetSemBrightness(brightness);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool InitAcquireBSEParam()
|
|
|
+ {
|
|
|
+
|
|
|
+ // get scan controller
|
|
|
+ var pScanController = m_ScanHardwareMgr;
|
|
|
+
|
|
|
+
|
|
|
+ if (!pScanController.Init())
|
|
|
+ {
|
|
|
+ log.Error(" failed to get scan control.");
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // set dwell time
|
|
|
+ if (!pScanController.SetDwellTime(DwellTimeLevel.Low))
|
|
|
+ {
|
|
|
+ //log.Error("SetBSEParam: failed to set dwell time (%d) for bruker system.", nBrukerDwellTime);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // set image size
|
|
|
+ if (!pScanController.SetImageSize(imgwidth, imgheight))
|
|
|
+ {
|
|
|
+ // failed to set dwell time
|
|
|
+ log.Error(" failed to set ImageSize");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|