Example #1
0
        private double GetBestGapDistance(Services.RBSK.RBSK rbsk, Action <double> progressCallBack = null)
        {
            //Caluclate gap distnace if it hasn't been set
            //Auto Find the gap distance
            //Scan from 20 - 300, the range which gives us consistent results is the right one
            int start    = 20;
            int end      = 300;
            int interval = 1;

            Video.SetFrame(100);
            Image <Gray, Byte>       firstFrame = Video.GetGrayFrameImage();
            Dictionary <int, PointF> nosePoints = new Dictionary <int, PointF>();

            for (int i = start; i <= end; i += interval)
            {
                if (Cancelled)
                {
                    return(-1);
                }

                using (Image <Gray, Byte> filteredImage = firstFrame.SmoothMedian(5))
                    using (Image <Gray, Byte> binaryImage = filteredImage.ThresholdBinary(new Gray(30), new Gray(255)))
                    {
                        rbsk.Settings.GapDistance = i;
                        Point[]  temp        = null;
                        PointF[] mousePoints = RBSKService.RBSKParallel(binaryImage, rbsk, ref temp);

                        if (mousePoints != null)
                        {
                            //We've found a set of points for this gap distance, store it
                            nosePoints.Add(i, mousePoints[2]);
                        }
                    }
                double progressValue = ((i - start) / ((double)end - start)) * 100;
                if (progressCallBack != null)
                {
                    progressCallBack(progressValue);
                }
            }

            const double threshold         = 20;
            PointF?      previousPoint     = null;
            List <int>   currentSelection  = new List <int>();
            int          bestCounter       = 0;
            double       bestDistanceSoFar = -1;

            foreach (KeyValuePair <int, PointF> kvp in nosePoints)
            {
                if (Cancelled)
                {
                    return(-1);
                }

                PointF currentPoint = kvp.Value;

                //Do we have a value?
                if (previousPoint.HasValue)
                {
                    //Is the previous point within the threshold distance of the current point
                    if (currentPoint.Distance(previousPoint.Value) < threshold)
                    {
                        currentSelection.Add(kvp.Key);
                        previousPoint = currentPoint;
                    }
                    else
                    {
                        //We're not within the threshold, compare the current list to see if it's the best
                        if (currentSelection.Count > bestCounter)
                        {
                            bestCounter       = currentSelection.Count;
                            bestDistanceSoFar = currentSelection.Average();
                        }

                        currentSelection.Clear();
                        previousPoint = null;
                    }
                }
                else
                {
                    previousPoint = currentPoint;
                }
            }

            if (currentSelection.Count > bestCounter)
            {
                bestDistanceSoFar = currentSelection.Average();
            }

            if (bestDistanceSoFar == -1)
            {
                bestDistanceSoFar = 100;
            }

            return(bestDistanceSoFar);
        }
Example #2
0
        private Dictionary <int, ISingleFrameResult> GenerateDictionary()
        {
            //const int SecondBinaryThresold = 10;
            const double movementDelta = 15;

            Services.RBSK.RBSK rbsk = MouseService.GetStandardMouseRules();

            if (GapDistance <= 0)
            {
                GapDistance = GetBestGapDistance(rbsk);
            }

            rbsk.Settings.GapDistance     = GapDistance;
            rbsk.Settings.BinaryThreshold = ThresholdValue;

            Dictionary <int, ISingleFrameResult> results = new Dictionary <int, ISingleFrameResult>();

            Video.Reset();
            int counter = 0;

            int frameCount = Video.FrameCount;

            while (true)
            {
                if (Paused)
                {
                    continue;
                }

                if (Cancelled)
                {
                    break;
                }

                using (Image <Bgr, byte> frame = Video.GetFrameImage())
                {
                    if (frame == null)
                    {
                        break;
                    }

                    if (Roi != Rectangle.Empty)
                    {
                        frame.ROI = Roi;
                    }

                    double waist, waistArea, waistArea2, waistArea3, waistArea4;
                    PointF centroid;

                    //if (counter == 500)
                    //{
                    //    frame.ROI = new Rectangle(0,0,1,1);
                    //}

                    PointF[] headPoints = ProcessFrame(frame, rbsk, out waist, out waistArea, out waistArea2, out waistArea3, out waistArea4, out centroid, true);

                    if (Roi != Rectangle.Empty)
                    {
                        centroid.X += Roi.X;
                        centroid.Y += Roi.Y;

                        if (headPoints != null)
                        {
                            headPoints[0].X += Roi.X;
                            headPoints[0].Y += Roi.Y;
                            headPoints[1].X += Roi.X;
                            headPoints[1].Y += Roi.Y;
                            headPoints[2].X += Roi.X;
                            headPoints[2].Y += Roi.Y;
                            headPoints[3].X += Roi.X;
                            headPoints[3].Y += Roi.Y;
                            headPoints[4].X += Roi.X;
                            headPoints[4].Y += Roi.Y;
                        }
                    }

                    //Console.WriteLine(waist + " " + waistArea);
                    //if (headPoints != null)
                    //{
                    //    foreach (var point in headPoints)
                    //    {
                    //        frame.Draw(new CircleF(point, 2), new Bgr(Color.Yellow), 2);
                    //    }
                    //}

                    //ImageViewer.Show(frame);
                    ISingleFrameResult frameResult = ModelResolver.Resolve <ISingleFrameResult>();
                    frameResult.HeadPoints   = headPoints;
                    frameResult.CentroidSize = waist;
                    frameResult.PelvicArea   = waistArea;
                    frameResult.PelvicArea2  = waistArea2;
                    frameResult.PelvicArea3  = waistArea3;
                    frameResult.PelvicArea4  = waistArea4;
                    frameResult.Centroid     = centroid;
                    results.Add(counter, frameResult);
                    counter++;

                    if (ProgressUpdates != null)
                    {
                        ProgressUpdates(this, new RBSKVideoUpdateEvent((double)counter / frameCount));
                    }
                }
            }

            if (Cancelled)
            {
                return(results);
            }

            //Find the most confident run of head detections
            List <List <HeadPointHolder> > confidentPoints = new List <List <HeadPointHolder> >();
            PointF lastPoint = PointF.Empty;
            List <HeadPointHolder> currentList = new List <HeadPointHolder>();
            double currentTotalMovement        = 0;

            for (int i = 0; i < results.Count; i++)
            {
                PointF[] headPoints = results[i].HeadPoints;

                if (headPoints == null)
                {
                    //No head found, use alternative methods
                    if (currentList.Count > 0)
                    {
                        confidentPoints.Add(currentList);
                    }
                    currentList          = new List <HeadPointHolder>();
                    lastPoint            = PointF.Empty;
                    currentTotalMovement = 0;
                    //Console.WriteLine("Head points are null " + i);
                    continue;
                }

                //Check against expected position
                PointF currentPoint = headPoints[2];

                if (lastPoint.IsEmpty)
                {
                    lastPoint = currentPoint;
                    currentList.Add(new HeadPointHolder(i, currentPoint, currentTotalMovement));
                    continue;
                }

                double distance = lastPoint.Distance(currentPoint);
                if (distance < movementDelta)
                {
                    //Acceptable
                    currentTotalMovement += distance;
                    currentList.Add(new HeadPointHolder(i, currentPoint, currentTotalMovement));
                    lastPoint = currentPoint;
                }
                else
                {
                    if (currentList.Count > 0)
                    {
                        confidentPoints.Add(currentList);
                    }
                    currentList          = new List <HeadPointHolder>();
                    lastPoint            = PointF.Empty;
                    currentTotalMovement = 0;
                    //Console.WriteLine("Outside of range " + i);
                }
            }

            if (currentList.Count > 0)
            {
                confidentPoints.Add(currentList);
            }

            if (confidentPoints.Count == 0)
            {
                return(results);
            }

            //Find longest list with highest total movement
            List <HeadPointHolder> bestList = confidentPoints[0];

            //double currentMaxTraverse = bestList.Last().TotalDelta;
            foreach (List <HeadPointHolder> list in confidentPoints)
            {
                //double currentTotalDelta = list.Last().TotalDelta;
                if (list.Count > bestList.Count)
                {
                    //currentMaxTraverse = currentTotalDelta;
                    bestList = list;
                }
            }

            //We now have a confident set of headpoints
            int minIndex = bestList.Select(x => x.FrameNumber).Min();
            int maxIndex = bestList.Select(x => x.FrameNumber).Max();


            minIndex--;
            while (minIndex >= 0)
            {
                //Traverse backwards
                PointF[] lastPoints = results[minIndex + 1].HeadPoints;
                if (lastPoints != null)
                {
                    lastPoint = lastPoints[2];
                }
                else
                {
                    lastPoint = new PointF(-100, -100);
                }

                PointF[] headPoints = results[minIndex].HeadPoints;

                if (headPoints == null)
                {
                    //No head found, use alternative methods
                    int previousThreshold = rbsk.Settings.BinaryThreshold;
                    rbsk.Settings.BinaryThreshold = ThresholdValue2;
                    Video.SetFrame(minIndex);
                    PointF[] headPoints2 = null;
                    using (Image <Bgr, byte> frame = Video.GetFrameImage())
                    {
                        if (frame == null)
                        {
                            break;
                        }

                        if (Roi != Rectangle.Empty)
                        {
                            frame.ROI = Roi;
                        }

                        headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta);
                    }

                    rbsk.Settings.BinaryThreshold = previousThreshold;

                    if (headPoints2 != null)
                    {
                        //We've got a good location
                        //double temp = results[minIndex].CentroidSize;
                        results[minIndex].HeadPoints = headPoints2;
                        //results[minIndex].CentroidSize = temp;
                        //results[minIndex] = new Tuple<PointF[], double>(headPoints2, temp);
                    }
                    else
                    {
                        for (int i = 0; i <= minIndex; i++)
                        {
                            if (results.ContainsKey(i))
                            {
                                //double temp = results[i].Item2;
                                //results[i] = new Tuple<PointF[], double>(null, temp);
                                results[i].HeadPoints = null;
                            }
                        }

                        break;
                    }

                    minIndex--;
                    continue;
                }

                //Check against expected position
                PointF currentPoint = headPoints[2];

                if (lastPoint.Distance(currentPoint) < movementDelta)
                {
                    //Good point
                }
                else
                {
                    //Wrong point, search for another rbsk that falls within range
                    //if (minIndex == 17 || minIndex == 16)
                    //{
                    //    Console.WriteLine("");
                    //}

                    Video.SetFrame(minIndex);
                    PointF[] headPoints2 = null;
                    using (Image <Bgr, byte> frame = Video.GetFrameImage())
                    {
                        if (frame == null)
                        {
                            break;
                        }

                        if (Roi != Rectangle.Empty)
                        {
                            frame.ROI = Roi;
                        }

                        headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta);
                    }

                    if (headPoints2 != null)
                    {
                        //We've got a good location
                        //double temp = results[maxIndex].Item2;
                        //results[minIndex] = new Tuple<PointF[], double>(headPoints2, temp);
                        results[minIndex].HeadPoints = headPoints2;
                    }
                    else
                    {
                        //No other rbsk falls within range, use alternative methods
                        //Console.WriteLine("Need to use alternative methods");
                        for (int i = 0; i <= minIndex; i++)
                        {
                            if (results.ContainsKey(i))
                            {
                                //double temp = results[i].Item2;
                                //results[i] = new Tuple<PointF[], double>(null, temp);
                                results[i].HeadPoints = null;
                            }
                        }

                        break;
                    }
                }

                minIndex--;
            }

            maxIndex++;
            while (maxIndex < results.Count)
            {
                //Traverse backwards
                PointF[] lastPoints = results[maxIndex - 1].HeadPoints;
                if (lastPoints != null)
                {
                    lastPoint = lastPoints[2];
                }
                else
                {
                    lastPoint = new PointF(-100, -100);
                }

                PointF[] headPoints = results[maxIndex].HeadPoints;


                if (headPoints == null)
                {
                    //No head found, use alternative methods
                    int previousThreshold = rbsk.Settings.BinaryThreshold;
                    rbsk.Settings.BinaryThreshold = ThresholdValue2;
                    Video.SetFrame(maxIndex);
                    PointF[] headPoints2 = null;
                    using (Image <Bgr, byte> frame = Video.GetFrameImage())
                    {
                        if (frame == null)
                        {
                            break;
                        }

                        if (Roi != Rectangle.Empty)
                        {
                            frame.ROI = Roi;
                        }

                        headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta);
                    }

                    rbsk.Settings.BinaryThreshold = previousThreshold;

                    if (headPoints2 != null)
                    {
                        //We've got a good location
                        //double temp = results[maxIndex].Item2;
                        //results[maxIndex] = new Tuple<PointF[], double>(headPoints2, temp);
                        results[maxIndex].HeadPoints = headPoints2;
                    }
                    else
                    {
                        int max = results.Keys.Max();
                        for (int i = maxIndex; i <= max; i++)
                        {
                            if (results.ContainsKey(i))
                            {
                                //double temp = results[i].Item2;
                                //results[i] = new Tuple<PointF[], double>(null, temp);
                                results[i].HeadPoints = null;
                            }
                        }

                        break;
                    }

                    maxIndex++;
                    continue;
                }

                //Check against expected position
                PointF currentPoint = headPoints[2];

                if (lastPoint.Distance(currentPoint) < movementDelta)
                {
                    //Good point
                }
                else
                {
                    //Wrong point, search for another rbsk that falls within range
                    Video.SetFrame(maxIndex);
                    PointF[] headPoints2 = null;
                    using (Image <Bgr, byte> frame = Video.GetFrameImage())
                    {
                        if (frame == null)
                        {
                            break;
                        }

                        if (Roi != Rectangle.Empty)
                        {
                            frame.ROI = Roi;
                        }

                        headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta);
                    }

                    if (headPoints2 != null)
                    {
                        //We've got a good location
                        //double temp = results[maxIndex].Item2;
                        //results[maxIndex] = new Tuple<PointF[], double>(headPoints2, temp);
                        results[maxIndex].HeadPoints = headPoints2;
                    }
                    else
                    {
                        //No other rbsk falls within range, use alternative methods
                        //Console.WriteLine("Need to use alternative methods");
                        int max = results.Keys.Max();
                        for (int i = maxIndex; i <= max; i++)
                        {
                            if (results.ContainsKey(i))
                            {
                                //double temp = results[i].Item2;
                                //results[i] = new Tuple<PointF[], double>(null, temp);
                                results[i].HeadPoints = null;
                            }
                        }

                        break;
                    }
                }

                maxIndex++;
            }

            return(results);
        }