/// <summary> /// Create AssemblyZone based on differences to previously saved DepthSnapshot /// </summary> /// <param name="m_DepthCroppedSnapshot"></param> /// <param name="pDetectRemoval"></param> /// <returns></returns> private AssemblyZone createAssemblyZoneFromChanges(Image <Gray, Int32> currentDepthImageCropped, bool pDetectRemoval) { if (m_DepthCroppedSnapshot == null) { return(null); } Image <Gray, Byte> imageDeltaMaskByte; if (pDetectRemoval) { imageDeltaMaskByte = m_DepthCroppedSnapshot.Cmp(currentDepthImageCropped, Emgu.CV.CvEnum.CMP_TYPE.CV_CMP_LT); } else { imageDeltaMaskByte = m_DepthCroppedSnapshot.Cmp(currentDepthImageCropped, Emgu.CV.CvEnum.CMP_TYPE.CV_CMP_GT); } CvInvoke.cvShowImage(pDetectRemoval.ToString() + "Snapshot", imageDeltaMaskByte.Ptr); Image <Gray, Int32> imageDeltaMaskInt = imageDeltaMaskByte.Convert <Int32>(delegate(Byte b) { if (b == 0) { return(0); } else { return(Int32.MaxValue); } }); Image <Gray, Int32> imageDelta = m_DepthCroppedSnapshot.AbsDiff(currentDepthImageCropped).And(imageDeltaMaskInt); double valueThreshold; int areaThreshold; if (pDetectRemoval) { valueThreshold = SettingsManager.Instance.Settings.AssemblyZonesInputMinValueChangeRemoval; areaThreshold = SettingsManager.Instance.Settings.AssemblyZonesInputMinAreaRemoval; } else { valueThreshold = SettingsManager.Instance.Settings.AssemblyZonesInputMinValueChangeAdding; areaThreshold = SettingsManager.Instance.Settings.AssemblyZonesInputMinAreaAdding; } Image <Gray, Int16> thImage = imageDelta.Convert <Gray, Int16>(); thImage = thImage.ThresholdToZero(new Gray(valueThreshold * 20)); imageDelta = thImage.Convert <Gray, Int32>(); #region Draw bounderis around detected areas List <BlobBound> listBlobBounds = BlobManager.FindAllBlob(imageDelta, pDetectRemoval, areaThreshold, valueThreshold); if (listBlobBounds.Count > 0) { BlobBound e = listBlobBounds.First(); Rectangle bounds = e.Rect; Polygon contourInGlobalImage = new Polygon(); foreach (Vector2 v in e.Contour.Points) { if (AdminView.Instance.IsKinectActive) { contourInGlobalImage.Points.Add(new Vector2(v.X + SettingsManager.Instance.Settings.SettingsTable.KinectDrawing_AssemblyArea.X, v.Y + SettingsManager.Instance.Settings.SettingsTable.KinectDrawing_AssemblyArea.Y)); } else { contourInGlobalImage.Points.Add(new Vector2(v.X + SettingsManager.Instance.Settings.SettingsTable.EnsensoDrawing_AssemblyArea.X, v.Y + SettingsManager.Instance.Settings.SettingsTable.EnsensoDrawing_AssemblyArea.Y)); } } if (AdminView.Instance.IsKinectActive) { return(AssemblyZoneManager.Instance.createAssemblyZoneFromFactory(bounds.X + SettingsManager.Instance.Settings.SettingsTable.KinectDrawing_AssemblyArea.X, bounds.Y + SettingsManager.Instance.Settings.SettingsTable.KinectDrawing_AssemblyArea.Y, bounds.Width, bounds.Height, e.BlobMask, true, pDetectRemoval, e.Area, contourInGlobalImage)); } else { return(AssemblyZoneManager.Instance.createAssemblyZoneFromFactory(bounds.X + SettingsManager.Instance.Settings.SettingsTable.EnsensoDrawing_AssemblyArea.X, bounds.Y + SettingsManager.Instance.Settings.SettingsTable.EnsensoDrawing_AssemblyArea.Y, bounds.Width, bounds.Height, e.BlobMask, true, pDetectRemoval, e.Area, contourInGlobalImage)); } } #endregion return(null); }
/// <summary> /// /// </summary> /// <param name="pImage"></param> /// <param name="pDetectRemoval"></param> /// <param name="pMinArea"></param> /// <param name="pValueThreshold"></param> /// <returns></returns> public static List <BlobBound> FindAllBlob(Image <Gray, Int32> pImage, bool pDetectRemoval, double pMinArea = 0.0, double pValueThreshold = 0.0) { List <BlobBound> retList = new List <BlobBound>(); //Arbitray factor to compensate biger value bandwith of new Image formate Image <Bgra, Byte> outputImage = pImage.Convert <Bgra, Byte>(); outputImage._GammaCorrect(0.5); #region using contour //only RETR_TYPE.CV_RETR_CCOMP dose work with Int32 for (Contour <System.Drawing.Point> contours = pImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_CCOMP); contours != null; contours = contours.HNext) { Seq <System.Drawing.Point> convexHull = contours.GetConvexHull(ORIENTATION.CV_CLOCKWISE); if (contours.BoundingRectangle.Width > 0 && contours.BoundingRectangle.Height > 0 && convexHull.Area > pMinArea) { //Approximiere Kontur durch ein Polygon //using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation //Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); Polygon poly = new Polygon(); foreach (Point p in convexHull) { poly.Points.Add(new Vector2(p.X, p.Y)); } Rectangle bounds = contours.BoundingRectangle; double summedValues = 0; int area = 0; bool[,] mask = new bool[bounds.Width, bounds.Height]; Array.Clear(mask, 0, mask.Length); for (int y = bounds.Y; y < bounds.Height + bounds.Y; y++) { for (int x = bounds.X; x < bounds.Width + bounds.X; x++) { if (pImage.Data[y, x, 0] > 0 && convexHull.InContour(new PointF(x, y)) > 0) { summedValues += pImage.Data[y, x, 0]; area++; mask[x - bounds.X, y - bounds.Y] = true; } } } if (area > 0 && summedValues / area > pValueThreshold) { BlobBound bbound = new BlobBound(bounds, area, (int)summedValues, mask, poly); retList.Add(bbound); //outputImage.Draw(bbound.Points, GREEN, 1); outputImage.Draw(bounds, BLUE, 1); outputImage.Draw(convexHull, RED, 1); } } } #endregion CvInvoke.cvShowImage(pDetectRemoval.ToString() + "-DepthChanges", outputImage.Ptr); retList.Sort((a, b) => a.Area.CompareTo(b.Area)); retList.Reverse(); return(retList); }