/// <summary>
        /// Find rectangles in image and add possible rectangle candidates as temporary but known objects or updates
        /// existing objects from previous frames.
        /// </summary>
        /// <param name="occlusionTracking"></param>
        /// <param name="grayImage"></param>
        /// <param name="outputImage"></param>
        /// <param name="updateTime"></param>
        /// <param name="objects"></param>
        private RectangularObject[] FindRectangles(bool occlusionTracking, Image<Gray, byte> grayImage, ref Image<Rgb, byte> outputImage, DateTime updateTime, RectangularObject[] objects)
        {
            var newObjects = new List<RectangularObject>();

            var imageWidth = grayImage.Width;
            var imageHeight = grayImage.Height;
            var pixels = imageWidth * imageHeight;

            var diagonal = Math.Sqrt(Math.Pow(imageWidth, 2) + Math.Pow(imageHeight, 2));

            var maxRestoreDistance = (MaxRestoreDistance / 100.0) * diagonal;

            using (var storage = new MemStorage())
            {
                for (var contours = grayImage.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, IsRetrieveExternal ? RETR_TYPE.CV_RETR_EXTERNAL : RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext)
                {
                    var lowApproxContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);

                    if (lowApproxContour.Area > ((MinContourArea / 100.0) * pixels) && lowApproxContour.Area < ((MaxContourArea / 100.0) * pixels)) //only consider contours with area greater than
                    {
                        if (IsRenderContent && IsDrawAllContours)
                            outputImage.Draw(lowApproxContour, Rgbs.BlueTorquoise, 1);
                        //outputImage.Draw(currentContour.GetConvexHull(ORIENTATION.CV_CLOCKWISE), Rgbs.BlueTorquoise, 2);

                        // Continue with next contour if current contour is not a rectangle.
                        List<DPoint> points;
                        if (!IsPlausibleRectangle(lowApproxContour, MinAngle, MaxAngle, MinDetectRightAngles, out points)) continue;

                        var highApproxContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);
                        if (IsRenderContent && IsDrawAllContours)
                            outputImage.Draw(highApproxContour, Rgbs.Yellow, 1);

                        var rectangle = highApproxContour.BoundingRectangle;
                        var minAreaRect = highApproxContour.GetMinAreaRect(storage);
                        var polygon = new Polygon(points.ToArray(), imageWidth, imageHeight);
                        var contourPoints = highApproxContour.ToArray();

                        if (!UpdateObject(occlusionTracking, maxRestoreDistance, rectangle, minAreaRect, polygon, contourPoints, updateTime, objects))
                        {
                            newObjects.Add(CreateObject(NextId(), rectangle, minAreaRect, polygon, contourPoints, updateTime));
                        }
                    }
                }
            }

            return newObjects.ToArray();
        }
        /// <summary>
        /// Tries to find objects that are occluded.
        /// </summary>
        /// <param name="image"></param>
        /// <param name="updateTime"></param>
        /// <param name="outputImage"></param>
        /// <param name="objects"></param>
        private void UpdateOccludedObjects(Image<Rgb, byte> image, ref Image<Rgb, byte> outputImage, DateTime updateTime, RectangularObject[] objects)
        {
            var imageWidth = image.Width;
            var imageHeight = image.Height;

            var mask = new Image<Gray, byte>(imageWidth, imageHeight);

            var occludedObjects = objects.Where(o => !Equals(o.LastUpdate, updateTime)).ToArray();

            // ignore if no objects are occluded but continue in case is render content set true to update debug view
            if (occludedObjects.Length < 1 && !IsRenderContent)
                return;

            foreach (var obj in occludedObjects)
                mask.Draw(obj.Shape, new Gray(1), -1);

            if (_depthImage == null) return;

            var occludedPartsImage = new Image<Gray, float>(imageWidth, imageHeight);

            var depthMapBinary = _depthImage.ThresholdBinaryInv(new Gray(255), new Gray(255));
            var depthMap = depthMapBinary;

            if (depthMap.Width != imageWidth || depthMap.Height != imageHeight)
            {
                var resizedDepthMap = new Image<Gray, float>(imageWidth, imageHeight);
                CvInvoke.cvResize(depthMap.Ptr, resizedDepthMap.Ptr, INTER.CV_INTER_CUBIC);
                depthMap.Dispose();
                depthMap = resizedDepthMap;
            }

            CvInvoke.cvCopy(depthMap.Ptr, occludedPartsImage.Ptr, mask);
            occludedPartsImage = occludedPartsImage.Erode(2).Dilate(2);

            var debugImage3 = occludedPartsImage.Convert<Rgb, byte>();

            var fixedImage = image.Or(debugImage3);
            fixedImage = fixedImage.Dilate(2).Erode(2);

            var debugImage = fixedImage.Copy();
            Task.Factory.StartNew(() =>
            {
                var bitmapSource = debugImage.ToBitmapSource(true);
                debugImage.Dispose();
                return bitmapSource;
            }).ContinueWith(t => DebugImageSource = t.Result);

            var outputImageEnclosed = outputImage;
            Parallel.ForEach(occludedObjects, obj => FindObjectByBlankingKnownObjects(true, fixedImage, ref outputImageEnclosed, updateTime, objects, obj));
        }
        /// <summary>
        /// Find an object by blanking out known objects except for the parameter object in the
        /// source image. If obj == null it will blank out all objects.
        /// </summary>
        /// <param name="occlusionTracking"></param>
        /// <param name="image"></param>
        /// <param name="outputImage"></param>
        /// <param name="objects"></param>
        /// <param name="obj"></param>
        /// <param name="updateTime"></param>
        private RectangularObject[] FindObjectByBlankingKnownObjects(bool occlusionTracking, Image<Rgb, byte> image, ref Image<Rgb, byte> outputImage, DateTime updateTime, RectangularObject[] objects, RectangularObject obj = null)
        {
            var objectsToBlank = obj != null ? objects.Where(o => o != obj) : objects;

            // Blank previous objects from previous frame
            var blankedImage = image.Copy();
            foreach (var otherObject in objectsToBlank)
            {
                blankedImage.Draw(otherObject.Shape, Rgbs.Black, -1);
            }

            var blankedImageGray = blankedImage.Convert<Gray, Byte>();

            var newObjects = FindRectangles(occlusionTracking, blankedImageGray, ref outputImage, updateTime, objects);

            blankedImageGray.Dispose();

            return newObjects;
        }