/// <summary> /// 根据图片判断是否需要保存 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static bool IsNeedToSave(String fileName) { try { using (Mat img = Cv2.ImRead(fileName, ImreadModes.GrayScale)) { return(IsNeedToSave(img)); } } catch (Exception ex) { NLogHelper.Trace("判断图片是否需要保存错误:" + ex.ToString()); return(false); } }
/// <summary> /// 是否需要保存图片 /// </summary> /// <param name="mat">指的是刚刚读进来的灰度图片</param> /// <returns></returns> public static bool IsNeedToSave(Mat mat) { if (mat == null || mat.IsDisposed) { return(false); } #region 预判断 if ((DateTime.Now - lastCallTime).TotalMilliseconds < 600) { //调用间隔至少为600ms NLogHelper.Trace("调用频繁,不需要截图"); return(false); } lastCallTime = DateTime.Now; #endregion #region 加载背景图片 if (backgroundMat == null || backgroundMat.IsDisposed) { if (!File.Exists(backgroundFile)) { NLogHelper.Trace("未找到背景图片:" + backgroundFile); backgroundMat = null; } else { try { backgroundMat = Cv2.ImRead(backgroundFile, ImreadModes.GrayScale); //去噪 backgroundMat = backgroundMat.MedianBlur(3); } catch (Exception ex) { NLogHelper.Trace("加载背景图片失败:" + ex); if (backgroundMat != null && backgroundMat.IsEnabledDispose) { backgroundMat.Dispose(); } backgroundMat = null; } } } #endregion #region 图片处理 ////进行图像灰度化 if (mat.Channels() > 1) { Mat outMat = new Mat(); Cv2.CvtColor(mat, outMat, ColorConversionCodes.BGRA2GRAY); mat = outMat; } //图片去噪 mat = mat.MedianBlur(3); int width = mat.Width; int height = mat.Height; //当前使用的背景图片 Mat usedBackgroundMat = null; if (backgroundMat != null) { if (backgroundMat.Width != width || backgroundMat.Height != height) { NLogHelper.Trace("背景图片与原图大小不一样,进行缩放"); usedBackgroundMat = backgroundMat.Resize(new Size(width, height)); } else { usedBackgroundMat = backgroundMat; } } //是否使用了lightMethod 光照模型去除背景, 拍摄同样一张图片但是不带物体 bool usedLightMethod = false; if (usedBackgroundMat != null && usedBackgroundMat.Width == width && usedBackgroundMat.Height == height) { if (lightMethod == 0) { mat = usedBackgroundMat - mat; usedLightMethod = true; } else if (lightMethod == 1) { mat.ConvertTo(mat, MatType.CV_32F); usedBackgroundMat.ConvertTo(usedBackgroundMat, MatType.CV_32F); mat = (1 - (usedBackgroundMat / mat)) * 255; mat.ConvertTo(mat, MatType.CV_8U); usedLightMethod = true; } } //二值化图像 if (usedLightMethod) { mat = mat.Threshold(30, 255, ThresholdTypes.Binary); } else { mat = mat.Threshold(140, 255, ThresholdTypes.Binary); } #endregion #region 联通组件 ConnectedComponents components = mat.ConnectedComponentsEx(); List <ConnectedComponents.Blob> blobList = new List <ConnectedComponents.Blob>(); for (int i = 0; i < components.Blobs.Count; i++) { if (i == 0) { //背景, continue; } ConnectedComponents.Blob blob = components.Blobs[i]; //实际区域大小 if (blob.Area > MinArea && blob.Width > MinWidth && blob.Height > MinHeight) { if (blob.Width > width * 0.9 && blob.Height > 0.9) { //发现超大物体,此物体有可能是背景或者其它干扰 NLogHelper.Trace("超大物体忽略"); } else { //一瓶矿泉水 width = 227 height=171 area=15907 blobList.Add(blob); } } } NLogHelper.Trace(string.Format("原图共有{0}个物体", blobList.Count)); #endregion #region 判断是否需要截图 //获取上一次的blobs List <ConnectedComponents.Blob> oldLastBlobs = lastBlobList; lastBlobList = blobList; if (blobList.Count == 0) { //没有图片,不需要保存 NLogHelper.Trace("没有图片,不需要保存"); return(false); } //获取最大的宽度的项 ConnectedComponents.Blob maxItem = blobList.OrderByDescending(r => r.Width).First(); if (oldLastBlobs == null || oldLastBlobs.Count == 0) { //之前没有图片 或者 中间范围内没有图片 if (maxItem.Width > width * 0.7 && maxItem.Height > height * 0.4) { //最大的物体很大 NLogHelper.Trace("之前没有图像,最大的物体很大,进行保存"); return(true); } else { //查找位于中间的个体数量 List <ConnectedComponents.Blob> middleBlobs = FindMiddleObjects(width, blobList, 0.81); if (middleBlobs.Count > 0) { //中间有物体 NLogHelper.Trace("之前没有图像,中间有物体,进行保存"); return(true); } else { //中间没有物体或者物体没有完全到中间 NLogHelper.Trace("之前没有图像,中间没有物体或者物体没有完全到中间,进行保存"); return(false); } } } else { //if (maxItem.Width > width*0.7 && maxItem.Height> height*0.4) //{ // //最大的物体很大 // return true; //} //之前图片有物体 List <ConnectedComponents.Blob> newMiddleBlobs = FindMiddleObjects(width, blobList, 0.81); //获取中间旧的 List <ConnectedComponents.Blob> oldMiddleBlobs = FindMiddleObjects(width, oldLastBlobs, 0.81); if (newMiddleBlobs.Count == 0) { //中间没有,认为不需要截图 NLogHelper.Trace("之前有图像,新图中间没有,认为不需要截图"); return(false); } //新的中间有图 if (oldMiddleBlobs.Count == 0) { //之前有图片,但图片不在中间,新的又有了 NLogHelper.Trace("之前有图片,但图片不在中间,新的又有了,需要截图"); return(true); } else { int minDiff = 1;//任务现在和之前相差超过minDiff个物体需要截图 //现在和以前均有图片 if ((newMiddleBlobs.Count - oldMiddleBlobs.Count) > minDiff) { //现在跟置前有两个以上的不同图片 NLogHelper.Trace("现在跟之前有两个以上的不同图片,需要截图"); return(true); } else { ////先按最左点排序,再按中心点排序,再按照面积排序 升序 newMiddleBlobs = newMiddleBlobs.OrderBy(r => r.Left).ThenBy(r => r.Width).ThenBy(r => r.Centroid.Y).ThenBy(r => r.Area).ToList(); oldMiddleBlobs = oldMiddleBlobs.OrderBy(r => r.Left).ThenBy(r => r.Width).ThenBy(r => r.Centroid.Y).ThenBy(r => r.Area).ToList(); var lcsTuple = LCS(newMiddleBlobs, oldMiddleBlobs); List <ConnectedComponents.Blob> commonBlobs = lcsTuple.Item1; List <ConnectedComponents.Blob> onlyNewBlobs = lcsTuple.Item2; List <ConnectedComponents.Blob> onlyOldBlobs = lcsTuple.Item3; if (commonBlobs.Count == 0) { //现在和以前没有公共部分,截图 NLogHelper.Trace("现在和以前没有公共部分,需要截图"); return(true); } else if (onlyNewBlobs.Count == 0 && onlyOldBlobs.Count == 0) { //全部是公共部分 NLogHelper.Trace("现在和以前全部是公共部分,不需要截图"); return(false); } else if (onlyOldBlobs.Count == 0) { //新的部分多了,除此之外都是公共的 NLogHelper.Trace("新的部分多了,除此之外都是公共的,需要截图"); return(true); } else if (onlyNewBlobs.Count == 0) { //旧的部分多了,除此之外全是公共的 NLogHelper.Trace("旧的部分多了,除此之外全是公共的,不需要截图"); return(false); } else { //旧的部分,新的部分,公共的部分都有 NLogHelper.Trace("旧的部分,新的部分,公共的部分都有,需要截图"); return(true); } } } } #endregion }