/// <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. }
/// <summary> /// Performs object detection on the given frame. /// </summary> /// //public Rectangle[] ProcessFrame(Bitmap frame) //{ // using (FastBitmap fastBitmap = new FastBitmap(frame)) // { // return ProcessFrame(fastBitmap); // } //} /// <summary> /// Performs object detection on the given frame. /// </summary> /// public Rectangle[] ProcessFrame(Bitmap image) { // int colorChannel = // image.PixelFormat == PixelFormat.Format8bppIndexed ? 0 : channel; Rectangle[] objects; // Creates an integral image representation of the frame using (var fastBitmap = new FastBitmap(image, _classifier.Cascade.HasTiltedFeatures)) { // Creates a new list of detected objects. _detectedObjects.Clear(); var width = fastBitmap.Width; var height = fastBitmap.Height; // Update parameters only if different size if (_steps == null || width != _lastWidth || height != _lastHeight) { Update(width, height); } var window = Rectangle.Empty; // For each scaling step for (var i = 0; i < _steps.Length; i++) { var scaling = _steps[i]; // 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) { // If we are searching in greater to smaller mode, if (_scalingMode == ObjectDetectorScalingMode.GreaterToSmaller) { break; // it won't get bigger, so we should stop. } else { continue; // continue until it gets greater. } } // Check if the window is greater than the maximum size else if (window.Width > _maxSize.Width || window.Height > _maxSize.Height) { // If we are searching in greater to smaller mode, if (_scalingMode == ObjectDetectorScalingMode.GreaterToSmaller) { continue; // continue until it gets smaller. } break; // it won't get smaller, so we should stop. } // Grab some scan loop parameters var xStep = window.Width >> 3; var yStep = window.Height >> 3; var xEnd = width - window.Width; var yEnd = height - window.Height; // Parallel mode. Scan the integral image searching // for objects in the window with parallelization. var bag = new System.Collections.Concurrent.ConcurrentBag <Rectangle>(); var numSteps = (int)Math.Ceiling((double)yEnd / yStep); // For each pixel in the window column var window1 = window; Parallel.For( 0, numSteps, (j, options) => { var y = j * yStep; // Create a local window reference var localWindow = window1; localWindow.Y = y; // For each pixel in the window row for (var x = 0; x < xEnd; x += xStep) { if (options.ShouldExitCurrentIteration) { return; } localWindow.X = x; // Try to detect and object inside the window if (_classifier.Compute(fastBitmap, 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. if (_searchMode == ObjectDetectorSearchMode.NoOverlap) { foreach (var obj in bag) { if (!Overlaps(obj)) { _detectedObjects.Add(obj); } } } else if (_searchMode == ObjectDetectorSearchMode.Single) { if (bag.TryPeek(out window)) { _detectedObjects.Add(window); break; } } else { foreach (var obj in bag) { _detectedObjects.Add(obj); } } } } objects = _detectedObjects.ToArray(); if (_searchMode == ObjectDetectorSearchMode.Average) { objects = _match.Group(objects); } CheckSteadiness(objects); _lastObjects = objects; return(objects); // Returns the array of detected objects. }