Skip to content
This repository has been archived by the owner on Nov 19, 2020. It is now read-only.

Commit

Permalink
GH-899: Add an Example for IntegralImage2 Class
Browse files Browse the repository at this point in the history
  • Loading branch information
cesarsouza committed Sep 28, 2017
1 parent 90a88cd commit 84b2d94
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 36 deletions.
90 changes: 64 additions & 26 deletions Sources/Accord.Imaging/AForge.Imaging/IntegralImage.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
// Accord Imaging Library
// The Accord.NET Framework
// http://accord-framework.net
//
// AForge Image Processing Library
// AForge.NET framework
// http://www.aforgenet.com/framework/
//
// Copyright © AForge.NET, 2005-2010
// [email protected]
//
// Copyright © César Souza, 2009-2017
// cesarsouza at gmail.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//

namespace Accord.Imaging
{
Expand All @@ -14,42 +35,59 @@ namespace Accord.Imaging
using Accord.Math;

/// <summary>
/// Integral image.
/// Integral image.
/// </summary>
///
/// <remarks><para>The class implements integral image concept, which is described by
/// Viola and Jones in: <b>P. Viola and M. J. Jones, "Robust real-time face detection",
/// Int. Journal of Computer Vision 57(2), pp. 137–154, 2004</b>.</para>
///
/// <para><i>"An integral image <b>I</b> of an input image <b>G</b> is defined as the image in which the
/// intensity at a pixel position is equal to the sum of the intensities of all the pixels
/// above and to the left of that position in the original image."</i></para>
///
/// <para>The intensity at position (x, y) can be written as:</para>
/// <code>
/// x y
/// I(x,y) = SUM( SUM( G(i,j) ) )
/// i=0 j=0
/// </code>
///
/// <para><note>The class uses 32-bit integers to represent integral image.</note></para>
///
/// <para><note>The class processes only grayscale (8 bpp indexed) images.</note></para>
///
/// <remarks>
/// <para>
/// This class implements integral image concept, which is described by
/// Viola and Jones in: <b>P. Viola and M. J. Jones, "Robust real-time face detection",
/// Int. Journal of Computer Vision 57(2), pp. 137–154, 2004</b>.</para>
///
/// <para>
/// <i>"An integral image <b>I</b> of an input image <b>G</b> is defined as the image in which the
/// intensity at a pixel position is equal to the sum of the intensities of all the pixels
/// above and to the left of that position in the original image."</i></para>
///
/// <para>
/// The intensity at position (x, y) can be written as:</para>
/// <code>
/// x y
/// I(x,y) = SUM( SUM( G(i,j) ) )
/// i=0 j=0
/// </code>
///
/// <para>
/// <note>The class uses 32-bit integers to represent integral image.</note></para>
///
/// <para>
/// <note>The class processes only grayscale (8 bpp indexed) images.</note></para>
///
/// <para><note>This class contains two versions of each method: safe and unsafe. Safe methods do
/// checks of provided coordinates and ensure that these coordinates belong to the image, what makes
/// these methods slower. Unsafe methods do not do coordinates' checks and rely that these
/// coordinates belong to the image, what makes these methods faster.</note></para>
/// checks of provided coordinates and ensure that these coordinates belong to the image, what makes
/// these methods slower. Unsafe methods do not do coordinates' checks and rely that these
/// coordinates belong to the image, what makes these methods faster.</note></para>
///
/// <para>
/// This class implements the simplest upright representation of an integral image. For an integral
/// image that can represent squared integral images as well as tilted images at the same time, please
/// refer to <see cref="IntegralImage2"/>.</para>
/// </remarks>
///
/// <example>
/// <para>Sample usage:</para>
/// <code>
/// // create integral image
/// IntegralImage im = IntegralImage.FromBitmap( image );
/// IntegralImage im = IntegralImage.FromBitmap(image);
///
/// // get pixels' mean value in the specified rectangle
/// float mean = im.GetRectangleMean( 10, 10, 20, 30 )
/// float mean = im.GetRectangleMean(10, 10, 20, 30)
/// </code>
/// </remarks>
/// </example>
///
/// <seealso cref="IntegralImage2"/>
///
[Serializable]
public class IntegralImage : ICloneable
{
/// <summary>
Expand Down
17 changes: 16 additions & 1 deletion Sources/Accord.Imaging/IntegralImage2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,27 @@ namespace Accord.Imaging
/// </summary>
///
/// <remarks>
/// <para>
/// This class provides a unified representation for both <see cref="IntegralImage">
/// integral images</see>, squared integral images and tilted integral images under
/// the same class. This class can be used to provide more efficient transformations
/// whenever all those representations are required at the same time, such as when
/// using the Viola-Jones (Haar Cascade) object detector.</para>
///
/// <para>
/// Using this representation, both structures can be created in a single pass
/// over the data. This is interesting for real time applications. This class
/// also accepts a channel parameter indicating the Integral Image should be
/// computed using a specified color channel. This avoids costly conversions.
/// computed using a specified color channel. This avoids costly conversions.</para>
/// </remarks>
///
/// <example>
/// <code source="Unit Tests\Accord.Tests.Imaging\IntegralImage2Test.cs" region="doc_sum" />
/// <code source="Unit Tests\Accord.Tests.Imaging\IntegralImage2Test.cs" region="doc_image" />
/// </example>
///
/// <seealso cref="IntegralImage"/>
///
[SecurityCritical]
public unsafe class IntegralImage2 : IDisposable
{
Expand Down
57 changes: 48 additions & 9 deletions Unit Tests/Accord.Tests.Imaging/IntegralImage2Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,43 @@ namespace Accord.Tests.Imaging
using NUnit.Framework;
using Accord.Imaging.Converters;
using System.Drawing.Imaging;
using Accord.DataSets;

[TestFixture]
public class IntegralImage2Test
{

#pragma warning disable 0618

[Test]
public void lena_test()
{
string localPath = NUnit.Framework.TestContext.CurrentContext.TestDirectory;

#region doc_lena
// In this example, we will compute an integral image
// representation of Lena Söderberg's famous picture:
TestImages testImages = new TestImages(path: localPath);
Bitmap lena = testImages["lena.bmp"]; // get the image

// Create a new Integral Image (squared and tilted) from Lena's picture:
IntegralImage2 ii = IntegralImage2.FromBitmap(lena, computeTilted: true);

// Let's say we would like to get the summed area in the rectangular region
// delimited by pixel (34, 50) until pixels (60, 105). This is equivalent to
// the region under the rectangle (34, 50, 34+60, 50+105) = (34, 50, 94, 155):
long sum = ii.GetSum(34, 50, 94, 155); // this is the sum of values (1760032)

// Now let's say we would like to get the squared sum and tilted sum as well:
long ssum = ii.GetSum2(34, 50, 94, 155); // this is the sum of squared values (229508896)
long tsum = ii.GetSumT(34, 50, 94, 155); // this is the sum of tilted values (-593600)
#endregion

Assert.AreEqual(1760032, sum);
Assert.AreEqual(229508896, ssum);
Assert.AreEqual(-593600, tsum);
}

[Test]
public void GetSumTest()
{
Expand Down Expand Up @@ -88,13 +118,13 @@ public void GetSumTest3()
/*9*/ { 9,9,9,9,9,9,1,1,1,1,9,9,9,9,9 },
/*A*/ { 9,9,9,9,9,9,9,1,1,9,9,9,9,9,9 },
/*B*/ { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 },
/*C*/ { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 },
/*C*/ { 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 },
};

// -RSAT(x-1,y-1) = [6-1,2-1] = [ 5, 1] => [ 1, 5] OK
// +RSAT(x+w-1,y+w-1) = [6+6-1,2+6-1] = [11, 7] => [ 7,11] OK
// -RSAT(x+w-1-h,y+w-1+h) = [6+6-1-4,2+6-1+4] = [ 7,11] => [11, 7] OK
// +RSAT(x-h-1, y+h-1) = [6-4-1,2+4-1] = [ 1, 5] => [ 5, 1] OK
// -RSAT(x-1,y-1) = [6-1,2-1] = [ 5, 1] => [ 1, 5]
// +RSAT(x+w-1,y+w-1) = [6+6-1,2+6-1] = [11, 7] => [ 7,11]
// -RSAT(x+w-1-h,y+w-1+h) = [6+6-1-4,2+6-1+4] = [ 7,11] => [11, 7]
// +RSAT(x-h-1, y+h-1) = [6-4-1,2+4-1] = [ 1, 5] => [ 5, 1]

// int sum = -iit[5,1] + iit[11,7] - iit[7,11] + iit[1,5];

Expand Down Expand Up @@ -129,6 +159,8 @@ public void GetSumTest3()
[Test]
public void GetSumTest2()
{
#region doc_sum
// Let's say we have the following image representation:
byte[,] img =
{
{ 5, 2, 3, 4, 1 },
Expand All @@ -138,9 +170,17 @@ public void GetSumTest2()
{ 4, 1, 3, 2, 6 },
};

Bitmap bmp = Accord.Imaging.Tools.ToBitmap(img);
IntegralImage2 ii = IntegralImage2.FromBitmap(bmp, 0);
// Let's convert it to bitmap and
// pretend it is our input image:
Bitmap bmp = img.ToBitmap();

// Now, create an integral image from this bitmap:
IntegralImage2 ii = IntegralImage2.FromBitmap(bmp);

// The sum-table would be:
long[,] actual = ii.Image;

// Which would be the same as:
long[,] expected =
{
{ 0, 0, 0, 0, 0, 0 },
Expand All @@ -150,10 +190,9 @@ public void GetSumTest2()
{ 0, 11, 25, 39, 52, 65 },
{ 0, 15, 30, 47, 62, 81 }
};
#endregion


long[,] actual = ii.Image;

Assert.IsTrue(Matrix.IsEqual(expected, actual));

}
Expand Down

0 comments on commit 84b2d94

Please sign in to comment.