using System; using System.Linq; using System.Drawing; using System.Threading; using System.Diagnostics; using SHJX.Service.Common.Utils; using System.Collections.Generic; using SHJX.Service.Common.Logging; using Microsoft.Extensions.Logging; using AForge.Video.DirectShow; using SHJX.Service.Model.CRUDModules; namespace shjxCamera { /// /// 图像采集器,定时进行图像采集 /// 每次采样发布采样事件:ColorDataGrabed /// public class ColorData2Graber { private static readonly ILogger logger = LogFactory.BuildLogger(typeof(ColorData2Graber)); #region fields /// /// 采集到的色彩数据队列 /// private List LstColorDataPoints; #endregion #region properties /// /// 摄像头 /// public WebCamera2 WebCam { get; set; } /// /// 提取ROI区域色彩数据 /// protected ImageRGBanalysis2 ColorAnalysis { get; set; } /// /// 停止数据采集 /// protected bool IsStopGrab { get; set; } /// /// 每帧间隔采集时间,毫秒 /// public int Interval { get; set; } /// /// 图像目标区域 /// public Rectangle RectROI { get; set; } public int CurrExposure { get; set; } /// /// 当前状态:true=工作中,正在采集数据;false=空闲中,未采集数据; /// public bool IsWorking { get; set; } private Camera2Value cameraValueAll = new Camera2Value(); #endregion #region methods /// /// 构造色点采集器对象 /// /// public ColorData2Graber(WebCamera2 webcam) { WebCam = webcam ?? new WebCamera2(); ColorAnalysis = new ImageRGBanalysis2(); RectROI = new Rectangle(0, 0, 10, 10); LstColorDataPoints = new List(); Interval = 50; IsStopGrab = false; IsWorking = false; } /// /// 自动调整目标取图区域的位置 /// public Rectangle UpdateRoiPos(bool writeFlag) { try { Bitmap imgBitmap = WebCam.GrabImage2(); if (imgBitmap == null) { int cnt = 30; while (imgBitmap == null && cnt-- > 0) { logger.LogError(string.Format("摄像头2imgBitmap2 == null && cnt-- > 0")); Thread.Sleep(100); imgBitmap = WebCam.GrabImage2(); } if (imgBitmap == null) { logger.LogError(string.Format("摄像头2imgBitmap2 == null")); return Titration2Settings.SensorPara.RoiSample; } } //Random rd = new Random(); //string name = System.DateTime.Now.ToString("yyyyMMddHHmmss") + rd.ToString() + ".bmp"; //imgBitmap.Save("C:\\Users\\25109\\Desktop\\软件版本库\\测试文件\\高锰测试\\摄像2图片\\"+ name); logger.LogCritical(string.Format("22222222old roi=({0}, {1}, {2}, {3})", RectROI.X, RectROI.Y, RectROI.Right, RectROI.Bottom)); RectROI = ColorAnalysis.GetRoiPos(imgBitmap, Titration2Settings.SensorPara.RoiSample, 35); // 定位新的目标区域坐标 RectROI.Offset(Titration2Settings.SensorPara.RoiOffsetX, 0); // 加入偏移量 if (Titration2Settings.SensorPara.UseRoiMask) { // 计算目标区域的均值,以均值的1/2作为阈值查找RoiMask int sumR = 0, sumG = 0, sumB = 0; ColorAnalysis.GetTotalFromImage(imgBitmap, RectROI, ref sumR, ref sumG, ref sumB); sumB = Math.Min(10, sumB / (RectROI.Width * RectROI.Height) / 2); #region 检查信号值是否异常[=0] if (sumB < 0.5) { throw new Exception("信号值异常[0],滴定须终止。"); } #endregion Titration2Settings.SensorPara.RoiMaskPoints = ColorAnalysis.GetRoiMask(imgBitmap, RectROI, sumB); } logger.LogCritical(string.Format("22222222new roi=({0}, {1}, {2}, {3}), offset=({4},0)", RectROI.X, RectROI.Y, RectROI.Right, RectROI.Bottom, Titration2Settings.SensorPara.RoiOffsetX)); if (writeFlag) { ColorAnalysis.WriteRGBlog(imgBitmap, RectROI, "定位后数据" + RectROI.ToString()); } } catch (Exception ex) { logger.LogError(ex.ToString()); } return RectROI; } /// /// 自动调节曝光值 /// public void PresetLightParam(int maxRange) { logger.LogCritical("22222222自动调节曝光值"); WebCam.SetProperties(CameraControlProperty.Exposure, maxRange,CameraControlFlags.Manual); WebCam.GetPropertiesRange(CameraControlProperty.Exposure, out var min, out var max, out var size, out var value, out var flag); Thread.Sleep(1000); //min=-9,max=0;size=1;value=-7;flag=Manual; // 读取信号值 var cdp = GrabSignal(500); // 判断信号所在区间,小于额定值范围则缩小曝光值,大于额定范围则增大曝光值 CameraControlFlags flags = CameraControlFlags.Manual; WebCam.GetProperties(CameraControlProperty.Exposure, out int val, out flags); int maxcount = 10; double bsvBelow = 114; double bsvUp = 114; int valBelow = -9; int valUp = 0; double bsv = 0.0; bool flagJudge = true; ; while (maxcount > 0) { maxcount--; bsv = cdp.GetBSV(); if (bsv < 110) { bsvBelow = bsv; if (val.Equals(min)) break; val = Math.Min(max, Math.Max(maxRange, val - 1)); valBelow = val; logger.LogCritical($"22222222增大曝光值为:{val}"); } else if (bsv > 118) { bsvUp = bsv; if (val.Equals(max)) break; val = Math.Min(max, Math.Max(maxRange, val + 1)); valUp = val; logger.LogCritical($"22222222减少曝光值为:{val}"); } else { flagJudge = false; ; break; } WebCam.SetProperties(CameraControlProperty.Exposure, val, CameraControlFlags.Manual); Thread.Sleep(500); UpdateRoiPos(false); cdp = GrabSignal(500); } if (flagJudge) { val = 114 - bsvBelow > bsvUp - 114 ? valBelow : valUp; val = Math.Min(max, Math.Max(maxRange, val)); WebCam.SetProperties(CameraControlProperty.Exposure, val, CameraControlFlags.Manual); Thread.Sleep(500); ContinuePresetLightParam(); } WebCam.GetProperties(CameraControlProperty.Exposure, out val, out flags); CurrExposure = val; logger.LogCritical($"22222222新的曝光值为:{val}"); } public void ContinuePresetLightParam() { logger.LogCritical("22222222自动调节亮度值Brightness"); WebCam.GetVideoProcAmpPropertiesRange(VideoProcAmpProperty.Brightness, out var minb, out var maxb, out var sizeb, out var valueb, out var flagb); Thread.Sleep(1000); // 读取信号值 var cdp = GrabSignal(500); VideoProcAmpFlags flags = VideoProcAmpFlags.Manual; WebCam.GetVideoProcAmpProperties(VideoProcAmpProperty.Brightness, out int val, out flags); int maxcount = 40; while (maxcount > 0) { maxcount--; if (cdp.GetBSV() < 110) { if (val < minb) break; val = val + 1; logger.LogCritical($"22222222增大亮度值为:{val}"); } else if (cdp.GetBSV() > 118) { if (val > maxb) break; val = val - 1; logger.LogCritical($"22222222减少亮度值为:{val}"); } else { break; } WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Brightness, val, VideoProcAmpFlags.Manual); Thread.Sleep(500); UpdateRoiPos(false); cdp = GrabSignal(500); } if (cdp.GetBSV() > 118) {logger.LogCritical($"22222222新的亮度值为:{val}"); PresetLightParammanual(cameraValueAll, 10); } WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Brightness, out val, out flagb); CurrExposure = val; logger.LogCritical($"22222222新的亮度值为:{val}"); } public void PresetLightParammanual(Camera2Value cameraValue, int explosionRange) { cameraValueAll = cameraValue; //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Brightness, out var minb, out var maxb, out var sizeb, out var valueb, out var flagb); //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Contrast, out var minbc, out var maxbc, out var sizebc, out var valuebc, out var flagbc); //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Hue, out var minbh, out var maxbh, out var sizebh, out var valuebh, out var flagbh); //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Saturation, out var minbs, out var maxbs, out var sizebs, out var valuebs, out var flagbs); //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Sharpness, out var mins, out var maxs, out var sizes, out var values, out var flags); //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.WhiteBalance, out var minbw, out var maxbw, out var sizebw, out var valuebw, out var flagbw); //WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Gain, out var minbg, out var maxbg, out var sizebg, out var valuebg, out var flagbg); WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Brightness, cameraValue.Brightness, VideoProcAmpFlags.Manual); WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Contrast, cameraValue.Contrast, VideoProcAmpFlags.Manual); WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Sharpness, cameraValue.Sharpness, VideoProcAmpFlags.Manual); WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Gain, cameraValue.Gain, VideoProcAmpFlags.Manual); //WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Hue, 0, VideoProcAmpFlags.Manual); WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.Saturation, cameraValue.Saturation, VideoProcAmpFlags.Manual); WebCam.SetVideoProcAmpProperties(VideoProcAmpProperty.WhiteBalance, cameraValue.WhiteBalance, VideoProcAmpFlags.Manual); if (explosionRange!=10) { WebCam.SetProperties(CameraControlProperty.Exposure, explosionRange, CameraControlFlags.Manual); } Thread.Sleep(1000); UpdateRoiPos(true); GrabSignal(10); int threshold_gray = 5; // 色点过滤阈值 int threshold_hue = 5; // 色相偏移阈值 ColorPoint cp = Globals.Camera.SampleBackground("d1camera", threshold_gray, threshold_hue); //logger.LogCritical($"22222222亮度:{cameraValue.Brightness} 对比:{cameraValue.Contrast} 锐度:{cameraValue.Sharpness} 增益:{cameraValue.Gain} 曝光:{explosionRange};***色值:{cp.Hue}"); logger.LogCritical($"22222222亮度:{cameraValue.Brightness} 对比:{cameraValue.Contrast} 饱和度:{cameraValue.Saturation}" + $" 白平衡:{cameraValue.WhiteBalance} 锐度:{cameraValue.Sharpness} 增益:{cameraValue.Gain} 曝光: {explosionRange};***色值:{cp.Hue}"); //Random rd = new Random(); //string name = System.DateTime.Now.ToString("yyyyMMddHHmmss") + rd.ToString() + ".bmp"; //imgBitmap.Save("C:\\Users\\25109\\Desktop\\软件版本库\\测试文件\\高锰测试\\摄像2图片\\"+ name); } public void ShowParammanual() { // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Brightness, out var minb, out var maxb, out var sizeb, out var valueb, out var flagb); // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Contrast, out var minbc, out var maxbc, out var sizebc, out var valuebc, out var flagbc); // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Hue, out var minbh, out var maxbh, out var sizebh, out var valuebh, out var flagbh); // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Saturation, out var minbs, out var maxbs, out var sizebs, out var valuebs, out var flagbs); // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Sharpness, out var mins, out var maxs, out var sizes, out var values, out var flags); // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.WhiteBalance, out var minbw, out var maxbw, out var sizebw, out var valuebw, out var flagbw); // WebCam.GetVideoProcAmpPropertiesRange(AForge.Video.DirectShow.VideoProcAmpProperty.Gain, out var minbg, out var maxbg, out var sizebg, out var valuebg, out var flagbg); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Brightness, out var valuebb, out var flagbb); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Contrast, out var valuebcc, out var flagbcc); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Hue, out var valuebhh, out var flagbhh); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Saturation, out var valuebss, out var flagbss); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Sharpness, out var valuess, out var flagss); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.WhiteBalance, out var valuebww, out var flagbww); WebCam.GetVideoProcAmpProperties(AForge.Video.DirectShow.VideoProcAmpProperty.Gain, out var valuebgg, out var flagbgg); WebCam.GetProperties(CameraControlProperty.Exposure, out var exposure, out var flagex); logger.LogCritical($"22222222亮度:{valuebb} 对比:{valuebcc} 锐度:{valuess} 饱和度:{valuebss} 白平衡:{valuebww} 增益:{valuebgg} 曝光:{exposure} "); } /// /// 连续采集指定时长的信号值,计算并返回该时长的信号总值和均值 /// /// 指定采集时长 /// 信号统计数据 public ColorData2Point GrabSignal(int milsecCount) { if (milsecCount < 35) milsecCount = 500; IsWorking = true; ColorData2Point cdp; var rectRoi = RectROI; int vr = 0, vg = 0, vb = 0; var area = rectRoi.Width * rectRoi.Height; if (Titration2Settings.SensorPara.UseRoiMask && Titration2Settings.SensorPara.RoiMaskPoints is not null) { area = Titration2Settings.SensorPara.RoiMaskPoints.Count; } // 采集指定时长的数据,计算均值返回 LstColorDataPoints.Clear(); var timeLength = 0; IsStopGrab = false; var sw = new Stopwatch(); while (!IsStopGrab) { sw.Restart(); var bmp = WebCam.GrabImage2(); if (Titration2Settings.SensorPara.UseRoiMask && Titration2Settings.SensorPara.RoiMaskPoints != null) { ColorAnalysis.GetTotalFromImage(bmp, Titration2Settings.SensorPara.RoiMaskPoints, ref vr, ref vg, ref vb); } else { ColorAnalysis.GetTotalFromImage(bmp, rectRoi, ref vr, ref vg, ref vb); } //Random rd = new Random(); //string name = System.DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next().ToString() + ".bmp"; //bmp.Save("C:\\Users\\25109\\Desktop\\软件版本库\\测试文件\\高锰测试\\摄像2图片\\" + name); cdp = new ColorData2Point { Id = LstColorDataPoints.Count, Area = area, RTV = vr, GTV = vg, BTV = vb }; LstColorDataPoints.Add(cdp); // 加入队列保存 // 固定每帧图像间隔 if (sw.ElapsedMilliseconds >= Interval) { sw.Stop(); } else { Thread.Sleep(Interval - Convert.ToInt32(sw.ElapsedMilliseconds)); } // 是否已到指定时长,结束采集 timeLength += Interval; if (timeLength >= milsecCount) { break; } } var lstSort = LstColorDataPoints.OrderByDescending(c => c.GTV).ToList(); var nMedianPos = Convert.ToInt32(Math.Ceiling(lstSort.Count / 2.0)); cdp = lstSort[nMedianPos - 1]; logger.LogCritical($"22222222use r={cdp.GetRSV()},g={cdp.GetGSV()},b={cdp.GetBSV()},h={cdp.GetSaturation()}"); IsWorking = false; Messager.Send("GraberColorValue2", 300 - cdp.GetBSV()); return cdp; } #endregion #region 未启用 #if false public void SavePicture(string filename) { if (string.IsNullOrWhiteSpace(filename)) { WebCam.GrabImage().Save(filename); } } /// /// 定时拍照采集图像,在后台线程执行 /// public void StartGrab() { LstColorDataPoints.Clear(); IsStopGrab = false; if (WebCam == null) { return; } var thrGrab = new Thread(ImageGrabing) { IsBackground = true }; thrGrab.Start(); } /// /// 结束采集线程 /// public void StopGrab() { if (LogProgram != null) { LogProgram.Debug("StopGrab()"); } IsStopGrab = true; } /// /// 根据启停指令连续采集信号值,计算最后的frameCount帧数据并返回信号总值和均值 /// /// 参与计算的帧数 /// 信号统计数据 public ColorDataPoint GrabSignalWithFrame(int frameCount) { if (frameCount < 10) { frameCount = 10; } IsWorking = true; Bitmap bmp; ColorDataPoint cdp; Rectangle rectROI = RectROI; int vr = 0, vg = 0, vb = 0; int area = rectROI.Width * rectROI.Height; if (Titration2Settings.SensorPara.UseRoiMask && Titration2Settings.SensorPara.RoiMaskPoints != null) { area = Titration2Settings.SensorPara.RoiMaskPoints.Count; } // 采集指定时长的数据,计算均值返回 LstColorDataPoints.Clear(); int timelength = 0; IsStopGrab = false; Stopwatch sw = new Stopwatch(); while (!IsStopGrab) { sw.Restart(); bmp = WebCam.GrabImage(); // 拍照 if (Titration2Settings.SensorPara.UseRoiMask && Titration2Settings.SensorPara.RoiMaskPoints != null) { ColorAnalysis.GetTotalFromImage(bmp, Titration2Settings.SensorPara.RoiMaskPoints, ref vr, ref vg, ref vb); } else { ColorAnalysis.GetTotalFromImage(bmp, rectROI, ref vr, ref vg, ref vb); } cdp = new ColorDataPoint { Id = LstColorDataPoints.Count, Area = area, RTV = vr, GTV = vg, BTV = vb }; LstColorDataPoints.Add(cdp); // 加入队列保存 if (LstColorDataPoints.Count > frameCount) { LstColorDataPoints.RemoveAt(0); } if (LogProgram != null && PrintDebugLog == true) { LogProgram.Info(string.Format("a={0},b={1},c={2},d={3}", cdp.GetRSV(), cdp.GetGSV(), cdp.GetBSV(), cdp.GetSaturation())); } // 固定每帧图像间隔 if (sw.ElapsedMilliseconds >= Interval) { sw.Stop(); } else { Thread.Sleep(Interval - Convert.ToInt32(sw.ElapsedMilliseconds)); } // 是否已到指定时长,结束采集 timelength += Interval; if (timelength >= frameCount) { break; } } var lstSort = LstColorDataPoints.OrderByDescending(c => c.GTV).ToList(); var nMedianPos = Convert.ToInt32(Math.Ceiling(lstSort.Count / 2.0)); cdp = lstSort[nMedianPos - 1]; if (LogProgram != null && PrintDebugLog == true) { LogProgram.Info(string.Format("use a={0},b={1},c={2},d={3}", cdp.GetRSV(), cdp.GetGSV(), cdp.GetBSV(), cdp.GetSaturation())); } IsWorking = false; //ColorDataGrabed?.Invoke(this, new ColorDataGrabedEventArgs() { ColorPoint = cdp }); return cdp; } /// /// 固定间隔时间,循环采集图像 /// protected void ImageGrabing() { IsWorking = true; Bitmap bmp; ColorDataPoint cdp; Rectangle rectROI = RectROI; int vr = 0, vg = 0, vb = 0; int area = rectROI.Width * rectROI.Height; if (Titration2Settings.SensorPara.UseRoiMask && Titration2Settings.SensorPara.RoiMaskPoints != null) { if (LogProgram != null) { LogProgram.Debug("UseRoiMaskPoints = True"); } area = Titration2Settings.SensorPara.RoiMaskPoints.Count; } if (LogProgram != null) { LogProgram.Debug("area = " + area.ToString()); } Stopwatch sw = new Stopwatch(); while (!IsStopGrab) { sw.Restart(); bmp = WebCam.GrabImage(); if (Titration2Settings.SensorPara.UseRoiMask && Titration2Settings.SensorPara.RoiMaskPoints != null) { ColorAnalysis.GetTotalFromImage(bmp, Titration2Settings.SensorPara.RoiMaskPoints, ref vr, ref vg, ref vb); } else { ColorAnalysis.GetTotalFromImage(bmp, rectROI, ref vr, ref vg, ref vb); } cdp = new ColorDataPoint { Id = LstColorDataPoints.Count, Area = area, RTV = vr, GTV = vg, BTV = vb }; LstColorDataPoints.Add(cdp); // 加入队列保存 //if (ColorDataGrabed != null) //{ // ColorDataGrabed(this, new ColorDataGrabedEventArgs() { ColorPoint = cdp }); //} // 发布采样点事件 if (LogProgram != null && PrintDebugLog == true) { LogProgram.Debug(string.Format("a={0}, b={1}, c={2}", cdp.GetRSV(), cdp.GetGSV(), cdp.GetBSV())); } if (sw.ElapsedMilliseconds >= Interval) { sw.Stop(); } else { Thread.Sleep(Interval - Convert.ToInt32(sw.ElapsedMilliseconds)); } } IsWorking = false; } #endif #endregion } }