Beispiel #1
0
        /// <summary>
        ///   Gets the sum of the areas of the rectangular features in an integral image.
        /// </summary>
        ///
        public double GetSum(SIntegralImage image, int x, int y)
        {
            double sum = 0.0;

            if (!Tilted)
            {
                // Compute the sum for a standard feature
                foreach (HaarRectangle rect in Rectangles)
                {
                    sum += image.GetSum(x + rect.ScaledX, y + rect.ScaledY,
                                        rect.ScaledWidth, rect.ScaledHeight) * rect.ScaledWeight;
                }
            }
            else
            {
                // Compute the sum for a rotated feature
                foreach (HaarRectangle rect in Rectangles)
                {
                    sum += image.GetSumT(x + rect.ScaledX, y + rect.ScaledY,
                                         rect.ScaledWidth, rect.ScaledHeight) * rect.ScaledWeight;
                }
            }

            return(sum);
        }
Beispiel #2
0
        /// <summary>
        ///   Detects the presence of an object in a given window.
        /// </summary>
        ///
        public bool Compute(SIntegralImage image, Rectangle rectangle)
        {
            int x = rectangle.X;
            int y = rectangle.Y;
            int w = rectangle.Width;
            int h = rectangle.Height;

            double mean   = image.GetSum(x, y, w, h) * invArea;
            double factor = image.GetSum2(x, y, w, h) * invArea - (mean * mean);

            factor = (factor >= 0) ? Math.Sqrt(factor) : 1;


            // For each classification stage in the cascade
            foreach (HaarCascadeStage stage in cascade.Stages)
            {
                // Check if the stage has rejected the image
                if (stage.Classify(image, x, y, factor) == false)
                {
                    return(false); // The image has been rejected.
                }
            }

            // If the object has gone all stages and has not
            //  been rejected, the object has been detected.

            return(true); // The image has been detected.
        }
Beispiel #3
0
        /// <summary>
        ///   Classifies an image as having the searched object or not.
        /// </summary>
        public bool Classify(SIntegralImage image, int x, int y, double factor)
        {
            double value = 0;

            // For each feature in the feature tree of the current stage,
            foreach (HaarFeatureNode[] tree in Trees)
            {
                int current = 0;

                do
                {
                    // Get the feature node from the tree
                    HaarFeatureNode node = tree[current];

                    // Evaluate the node's feature
                    double sum = node.Feature.GetSum(image, x, y);

                    // And increase the value accumulator
                    if (sum < node.Threshold * factor)
                    {
                        value  += node.LeftValue;
                        current = node.LeftNodeIndex;
                    }
                    else
                    {
                        value  += node.RightValue;
                        current = node.RightNodeIndex;
                    }
                } while (current > 0);

                // Stop early if we have already surpassed the stage threshold value.
                //if (value > this.Threshold) return true;
            }

            // After we have evaluated the output for the
            //  current stage, we will check if the value
            //  is still lesser than the stage threshold.
            if (value < this.Threshold)
            {
                // If it is, the stage has rejected the current
                // image and it doesn't contains our object.
                return(false);
            }
            else
            {
                // The stage has accepted the current image
                return(true);
            }
        }
Beispiel #4
0
        /// <summary>
        ///   Performs object detection on the given frame.
        /// </summary>
        ///
        public Rectangle[] ProcessFrame(UnmanagedImage image)
        {
            // Creates an integral image representation of the frame
            SIntegralImage integralImage = SIntegralImage.FromBitmap(
                image, channel, classifier.Cascade.HasTiltedFeatures);

            // Creates a new list of detected objects.
            this.detectedObjects.Clear();

            int width  = integralImage.Width;
            int height = integralImage.Height;

            // Update parameters only if different size
            if (steps == null || width != lastWidth || height != lastHeight)
            {
                update(width, height);
            }


            Rectangle window = Rectangle.Empty;

            // For each scaling step
            foreach (float scaling in steps)
            {
                // Set the classifier window scale
                classifier.Scale = scaling;

                // Get the scaled window size
                window.Width  = (int)(baseWidth * scaling);
                window.Height = (int)(baseHeight * scaling);

                // Check if the window is lesser than the minimum size
                if (window.Width < minSize.Width && window.Height < minSize.Height &&
                    window.Width > maxSize.Width && window.Height > maxSize.Height)
                {
                    // If we are searching in greater to smaller mode,
                    if (scalingMode == ObjectDetectorScalingMode.GreaterToSmaller)
                    {
                        goto EXIT; // it won't get bigger, so we should stop.
                    }
                    else
                    {
                        continue; // continue until it gets greater.
                    }
                }


                // Grab some scan loop parameters
                int xStep = window.Width >> 3;
                int yStep = window.Height >> 3;

                int xEnd = width - window.Width;
                int yEnd = height - window.Height;

                // Check if we should run in parallel or sequential
                if (!UseParallelProcessing)
                {
                    // Sequential mode. Scan the integral image searching
                    // for objects in the window without parallelization.

                    // For every pixel in the window column
                    for (int y = 0; y < yEnd; y += yStep)
                    {
                        window.Y = y;

                        // For every pixel in the window row
                        for (int x = 0; x < xEnd; x += xStep)
                        {
                            window.X = x;

                            if (searchMode == ObjectDetectorSearchMode.NoOverlap && overlaps(window))
                            {
                                continue; // We have already detected something here, moving along.
                            }
                            // Try to detect and object inside the window
                            if (classifier.Compute(integralImage, window))
                            {
                                // an object has been detected
                                detectedObjects.Add(window);

                                if (searchMode == ObjectDetectorSearchMode.Single)
                                {
                                    goto EXIT; // Stop on first object found
                                }
                            }
                        }
                    }
                }

                else
                {
                    // Parallel mode. Scan the integral image searching
                    // for objects in the window with parallelization.
                    ConcurrentBag <Rectangle> bag = new ConcurrentBag <Rectangle>();

                    int numSteps = (int)Math.Ceiling((double)yEnd / yStep);

                    // For each pixel in the window column
                    Parallel.For(0, numSteps, (j, options) => {
                        int y = j * yStep;

                        // Create a local window reference
                        Rectangle localWindow = window;

                        localWindow.Y = y;

                        // For each pixel in the window row
                        for (int x = 0; x < xEnd; x += xStep)
                        {
                            if (options.ShouldExitCurrentIteration)
                            {
                                return;
                            }

                            localWindow.X = x;

                            // Try to detect and object inside the window
                            if (classifier.Compute(integralImage, localWindow))
                            {
                                // an object has been detected
                                bag.Add(localWindow);

                                if (searchMode == ObjectDetectorSearchMode.Single)
                                {
                                    options.Stop();
                                }
                            }
                        }
                    });

                    // If required, avoid adding overlapping objects at
                    // the expense of extra computation. Otherwise, only
                    // add objects to the detected objects collection.
                    switch (searchMode)
                    {
                    case ObjectDetectorSearchMode.NoOverlap:
                        foreach (Rectangle obj in bag.Where(obj => !overlaps(obj)))
                        {
                            detectedObjects.Add(obj);
                        }
                        break;

                    case ObjectDetectorSearchMode.Single:
                        if (bag.TryPeek(out window))
                        {
                            detectedObjects.Add(window);
                            goto EXIT;
                        }
                        break;

                    default:
                        foreach (Rectangle obj in bag)
                        {
                            detectedObjects.Add(obj);
                        }
                        break;
                    }
                }
            }


EXIT:

            Rectangle[] objects = detectedObjects.ToArray();

            checkSteadiness(objects);
            lastObjects = objects;

            return(objects); // Returns the array of detected objects.
        }