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 BCstatedic =new SortedDictionary(); 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; } } }