public override Image ProcessColorImage(Bitmap frame, ToteDetectionType detectionType, bool detectBins)
        {
            Image<Bgr, Byte> img = new Image<Bgr, Byte>(frame);

            //// Get The Thresh Image With Given Values
            //Image<Gray, byte> thresh = (threshData as BgrThreshData).InRange(img);
            //// Pixelate Image
            //threshData.Blur(ref thresh);
            //
            //
            //Image ret = base.AnalyzeImage(thresh, detectionType, detectBins);


            //frame.Dispose();
            //thresh.Dispose();

            img = img.SmoothMedian(11);
            img = img.SmoothGaussian(11);
            img = img.Erode(15);
            img = img.Dilate(10);

            // Try this: img.HoughCircles();

            Image<Gray, byte> thresh = img.InRange(new Bgr(110, 130, 100), new Bgr(164, 166, 181));
            Contour<Point> countor = thresh.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST);
            List<Contour<Point>> PlayingBalls = new List<Contour<Point>>(); ;
            while (countor != null)
            {
                // filter countors
                // convex hull countors
                if (countor.Area > 50)
                    PlayingBalls.Add(countor);
                   
                countor = countor.HNext;
            }
            float resolutionOffset = ((float)thresh.Width * thresh.Height) / (640.0f * 480.0f);


            foreach (Contour<Point> ball in PlayingBalls)
            {
                
                img.Draw(ball, new Bgr(255, 0, 0), (int)Math.Ceiling(3.0f));
                // draw left countors and their min enclosing circle (draw on img)
            }
          



            Image ret = img.ToBitmap();
            img.Dispose();
            return ret;
        }
        public Image ProcessImage(Bitmap frame, ToteDetectionType detectionType, bool detectBins)
        {
            Image<Hsv, Byte> img = new Image<Hsv, Byte>(frame);

            // Get The Thresh Image With Given Values
            Image<Gray, byte> thresh = threshData.InRange(img);

            // Pixelate Image
            threshData.Blur(ref thresh);


            Image ret = AnalyzeImage(img.Convert<Bgr, byte>(), thresh, detectionType, detectBins);


            thresh.Dispose();
            img.Dispose();
            return ret;
        }
        public override Image ProcessColorImage(Bitmap frame, ToteDetectionType detectionType, bool detectBins)
        {
            Image<Hsv, Byte> img = new Image<Hsv, Byte>(frame);
         

            // Get The Thresh Image With Given Values
            Image<Gray, byte> thresh = (threshData as HsvThreshData).InRange(img);

            // Pixelate Image
            threshData.Blur(ref thresh);


            Image ret = base.AnalyzeImage(thresh, detectionType, detectBins);


            thresh.Dispose();
            img.Dispose();
            return ret;
        }
        List<L_Shape> FindToteVisionTargets(ToteDetectionType tdt, Image<Gray, byte> thresh, float resolutionOffset, float imageWidth)
        {
            List<L_Shape> targets = new List<L_Shape>();
            Contour<Point> blob = thresh.FindContours();

            while (blob != null)
            {
                bool isL = false;

                if (blob.Area > 200 * resolutionOffset)
                    switch (tdt)
                    {
                        case ToteDetectionType.Math:
                            isL = IsL_ByMath(blob);
                            break;
                        case ToteDetectionType.Edges:
                            isL = IsL_ByEdges(blob);
                            break;
                        case ToteDetectionType.None:
                            isL = true;
                            break;
                    }

                if (isL)
                {
                    L_Shape s = new L_Shape(blob, IsRightL(blob));
                    targets.Add(s);
                }
                blob = blob.HNext;
            }
            return targets;
        }
        //Do Vision
        protected Image AnalyzeImage(Image<Gray, byte> thresh, ToteDetectionType detectionType, bool detectBins)
        {
            angleToBin = NotFoundFloat;

            // Create A Bgr Image So We Could Draw Stuff On The Threshold Image.
            Image<Bgr, Byte> threshToDraw = thresh.Convert<Bgr, byte>();

            float resolutionOffset = ((float)thresh.Width * thresh.Height) / (640.0f * 480.0f);


            List<L_Shape> targets = FindToteVisionTargets(detectionType, thresh, resolutionOffset, thresh.Width);
            foreach (L_Shape l in targets)
            {
                threshToDraw.Draw(l.shape, new Bgr(255, 0, 0), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
            }

            if (detectBins)
            {
                List<Contour<Point>> bins = FindBins(thresh, resolutionOffset, thresh.Width);
                double maxArea = 0.0f;
                foreach (Contour<Point> bin in bins)
                {
                    // Oz changes start
                    MCvMoments moment = bin.GetMoments();
                    PointF centerOfMass = new PointF((float)moment.GravityCenter.x, (float)moment.GravityCenter.y);
                    CircleF circleOfMass = new CircleF(centerOfMass, 4.590f);
                    threshToDraw.Draw(circleOfMass, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));

                    // Check if it's the biggest bin yet, if it is - calculate the angle to it
                    if (maxArea < bin.Area)
                    {
                        maxArea = bin.Area;
                        angleToBin = GetAngleToBin(bin, thresh.Size.Width / 2.0);
                    }

                    Seq<Point> convexHull = bin.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                    threshToDraw.Draw(convexHull, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
                    // Oz changes end
                    threshToDraw.Draw(bin.BoundingRectangle, new Bgr(0, 255, 0), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
                    PointF center = bin.GetMinAreaRect().center;
                    if (this.LastDepthMap!=null)
                        if ((this.LastDepthMap.GetDepth((Int32)center.X, (Int32)center.Y)) != 4080)
                            ((ProgrammersWindow)ProgrammersWindow.ActiveForm).updateBinDepth(this.LastDepthMap.GetDepth((Int32)center.X, (Int32)center.Y));


                }
            }


            L_Shape[] best_pair = FindBestPair(targets);
            if (best_pair[0] != null && best_pair[1] != null)
            {
                threshToDraw.Draw(best_pair[0].shape, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
                threshToDraw.Draw(best_pair[1].shape, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
            }


            // Draw A Red Cross All Over The Threshold Picture So We'D Know It'S Center
            threshToDraw.Draw(new Cross2DF(new PointF(thresh.Width / 2, thresh.Height / 2) , thresh.Width, thresh.Height), new Bgr(0, 0, 255), 1);

           

            Image ret = threshToDraw.ToBitmap();
            threshToDraw.Dispose();

            return ret;
        }
 //Prepare Image For Vision
 public abstract Image ProcessColorImage(Bitmap bmp, ToteDetectionType detectionType, bool detectBins);
        public VisionImage ProcessImage(Bitmap bmp, ToteDetectionType detectionType, bool detectBins, DepthMap depthMap = null)
        {
            LastDepthMap = depthMap;

            //processing depth image
            Bitmap processedBitmap = (Bitmap)ProcessColorImage(bmp, detectionType, detectBins);
            return new VisionImage(processedBitmap, depthMap);

        }
        //Do Vision
        protected Image AnalyzeImage(Image<Bgr, byte> original, Image<Gray, byte> thresh, ToteDetectionType detectionType, bool detectBins)
        {
            angleToBin = NotFoundFloat;

            float resolutionOffset = ((float)thresh.Width * thresh.Height) / (640.0f * 480.0f);


            //List<L_Shape> targets = FindToteVisionTargets(detectionType, thresh, resolutionOffset, thresh.Width);
            //foreach (L_Shape l in targets)
            //{
            //    original.Draw(l.shape, new Bgr(255, 0, 0), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
            //}

            //L_Shape[] best_pair = FindBestPair(targets);
            //if (best_pair[0] != null && best_pair[1] != null)
            //{
            //    original.Draw(best_pair[0].shape, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
            //    original.Draw(best_pair[1].shape, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
            //}


            if (detectBins)
            {
                List<Contour<Point>> bins = FindBins(thresh, resolutionOffset, thresh.Width);
                double maxArea = 0.0f;
                foreach (Contour<Point> bin in bins)
                {
                    // Oz changes start
                    MCvMoments moment = bin.GetMoments();
                    PointF centerOfMass = new PointF((float)moment.GravityCenter.x, (float)moment.GravityCenter.y);
                    CircleF circleOfMass = new CircleF(centerOfMass, 4.590f);
                    original.Draw(circleOfMass, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));

                    // Check if it's the biggest bin yet, if it is - calculate the angle to it
                    if (maxArea < bin.Area)
                    {
                        maxArea = bin.Area;
                        angleToBin = GetAngleToBin(bin, thresh.Size.Width / 2.0);
                    }

                    Seq<Point> convexHull = bin.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                    original.Draw(convexHull, new Bgr(0, 0, 255), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
                    // Oz changes end
                    original.Draw(bin.BoundingRectangle, new Bgr(0, 255, 0), (int)Math.Ceiling(3.0f * Math.Sqrt(resolutionOffset)));
                }
            }

            // Draw A Red Cross All Over The Threshold Picture So We'D Know It'S Center
            original.Draw(new Cross2DF(new PointF(thresh.Width / 2, thresh.Height / 2), thresh.Width, thresh.Height), new Bgr(0, 0, 255), 1);


            Image ret = original.ToBitmap();
            original.Dispose();

            return ret;
        }