Пример #1
0
        /// <summary>
        /// Gets the sum of the areas of the rectangular features in an integral image
        /// </summary>
        /// <param name="image"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public double GetSum(ImageHelper image, int x, int y)
        {
            double sum = 0.0;

            if (!Tilted)
            {
                // Compute the sum for a standard feature
                foreach (RectangleHelper 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 (RectangleHelper rect in Rectangles)
                {
                    sum += image.GetSumT(x + rect.scaledX, y + rect.scaledY,
                        rect.scaledWidth, rect.scaledHeight) * rect.scaledWeight;
                }
            }

            return sum;
        }
Пример #2
0
        /// <summary>
        /// This is where we do the detection for an image passing in the interest window
        /// </summary>
        /// <param name="pImage"></param>
        /// <param name="pWindow"></param>
        /// <returns></returns>
        public bool Compute(ImageHelper pImage, Rectangle pWindow)
        {
            // grab the dimensions
            int x = pWindow.X;
            int y = pWindow.Y;
            int w = pWindow.Width;
            int h = pWindow.Height;

            // figure out the details of the window in the image
            double mean = pImage.GetSum(x, y, w, h) * invArea;
            double factor = pImage.GetSum2(x, y, w, h) * invArea - (mean * mean);

            // do the math to adjust the factor
            factor = (factor >= 0) ? Math.Sqrt(factor) : 1;

            // For each classification stage in the cascade
            foreach (Stage stage in cascade.stages)
            {
                // Check to see if the image was rejected
                if (stage.Classify(pImage, x, y, factor) == false)
                {
                    return false; // If it was, we tell the caller that we were rejected.
                }
            }

            // If we've gone through all the stages and were not rejected, the object was detected inside the window
            return true;
        }
Пример #3
0
        /// <summary>
        /// Constructor passing in an unmanaged image, a channel, and the flag to compute a tilted image
        /// </summary>
        /// <param name="pImage"></param>
        /// <param name="pChannel"></param>
        /// <param name="pComputeTilted"></param>
        /// <returns></returns>
        public static ImageHelper FromBitmap(AForge.Imaging.UnmanagedImage pImage, int pChannel, bool pComputeTilted)
        {
            // check image format, we'll have the same issue with bitmaps here as we did before
            if (!(pImage.PixelFormat == PixelFormat.Format8bppIndexed ||
                pImage.PixelFormat == PixelFormat.Format24bppRgb ||
                pImage.PixelFormat == PixelFormat.Format32bppArgb))
            {
                throw new AForge.Imaging.UnsupportedImageFormatException("Only grayscale and 24 bpp RGB images are supported.");
            }

            // find the pixel size
            int pixelSize = System.Drawing.Image.GetPixelFormatSize(pImage.PixelFormat) / 8;

            // get source image size
            int pWidth = pImage.Width;
            int pHeight = pImage.Height;
            int pStride = pImage.Stride;
            int pOffset = pStride - pWidth * pixelSize;

            // create integral image
            ImageHelper im = new ImageHelper(pWidth, pHeight, pComputeTilted);
            int* nSum = im.intImage, sSum = im.squaredImage, tSum = im.tiltedImage;

            // compute the adjusted widths and heights for the other two operations
            int nWidth = im.nWidth, nHeight = im.nHeight;
            int tWidth = im.tWidth, tHeight = im.tHeight;

            // We're going to have an issue if the channel doesn't support 8 bpp
            if (pImage.PixelFormat == PixelFormat.Format8bppIndexed && pChannel != 0)
                throw new ArgumentException("Only the first channel is available for 8 bpp images.", "channel");

            // grab the image pointer src
            byte* srcStart = (byte*)pImage.ImageData.ToPointer() + pChannel;

            // do the job
            byte* src = srcStart;

            // for each line
            for (int y = 1; y <= pHeight; y++)
            {
                int yy = nWidth * (y);
                int y1 = nWidth * (y - 1);

                // for each pixel
                for (int x = 1; x <= pWidth; x++, src += pixelSize)
                {
                    // set p1 to the src
                    // and square it for p2
                    int p1 = *src;
                    int p2 = p1 * p1;

                    // find the indexes for each sum
                    int r = yy + (x);
                    int a = yy + (x - 1);
                    int b = y1 + (x);
                    int c = y1 + (x - 1);

                    // and sum them up!
                    nSum[r] = p1 + nSum[a] + nSum[b] - nSum[c];
                    sSum[r] = p2 + sSum[a] + sSum[b] - sSum[c];
                }
                src += pOffset;
            }

            // if we're computing the tilted image as well, there is a lot more going on
            if (pComputeTilted)
            {
                // grab the source
                src = srcStart;

                // Left-to-right, top-to-bottom pass
                for (int y = 1; y <= pHeight; y++, src += pOffset)
                {
                    // compute the new yy and y1
                    int yy = tWidth * (y);
                    int y1 = tWidth * (y - 1);

                    for (int x = 2; x < pWidth + 2; x++, src += pixelSize)
                    {
                        // find the indexes
                        int a = y1 + (x - 1);
                        int b = yy + (x - 1);
                        int c = y1 + (x - 2);
                        int r = yy + (x);

                        // and sum them up
                        tSum[r] = *src + tSum[a] + tSum[b] - tSum[c];
                    }
                }

                {
                    int yy = tWidth * (pHeight);
                    int y1 = tWidth * (pHeight + 1);

                    for (int x = 2; x < pWidth + 2; x++, src += pixelSize)
                    {
                        int a = yy + (x - 1);
                        int c = yy + (x - 2);
                        int b = y1 + (x - 1);
                        int r = y1 + (x);

                        tSum[r] = tSum[a] + tSum[b] - tSum[c];
                    }
                }

                // Now do it Right-to-left, and bottom-to-top
                for (int y = pHeight; y >= 0; y--)
                {
                    // compute the new values
                    int yy = tWidth * (y);
                    int y1 = tWidth * (y + 1);

                    for (int x = pWidth + 1; x >= 1; x--)
                    {
                        // grab the indexes
                        int r = yy + (x);
                        int b = y1 + (x - 1);

                        // and add them up
                        tSum[r] += tSum[b];
                    }
                }

                for (int y = pHeight + 1; y >= 0; y--)
                {
                    // grab the new value
                    int yy = tWidth * (y);

                    for (int x = pWidth + 1; x >= 2; x--)
                    {
                        // compute the indexes
                        int r = yy + (x);
                        int b = yy + (x - 2);

                        // and add them up
                        tSum[r] -= tSum[b];
                    }
                }
            }

            // finally return the restult... All the math should be done by this point
            return im;
        }
Пример #4
0
        /// <summary>
        ///   Classifies an image as having the searched object or not.
        /// </summary>
        public bool Classify(ImageHelper pImage, int row, int column, double pFactor)
        {
            // Keep track of how close to the threshold we are.
            double achievedThreshold = 0;

            // For each feature in the feature tree of the current stage,
            foreach (FeatureNode[] node in nodes)
            {
                int current = 0;
                do
                {
                    // Get the feature node from the current branch in the node tree
                    FeatureNode feature = node[current];

                    // Evaluate the node's feature
                    double sum = feature.mFeature.GetSum(pImage, row, column);

                    // And increase the value accumulator
                    if (sum < feature.mThreshold * pFactor)
                    {
                        achievedThreshold += feature.mLeftValue;
                        current = feature.mLeft;
                    }
                    else
                    {
                        achievedThreshold += feature.mRightValue;
                        current = feature.mRight;
                    }

                } while (current > 0);
            }

            // If the achieved threshold is greater than the desired threshold we have found a face!!
            if (achievedThreshold <= this.threshold)
            {
                // Otherwise our image doesn't contain what we're looking for.
                return false;
            }
            else
            {
                // We had a match!
                return true;
            }
        }